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 06:41:16.110
2025-07-02 06:41:16.110 act = <firebird.qa.plugin.Action object at [hex]>
2025-07-02 06:41:16.110
2025-07-02 06:41:16.111     @pytest.mark.version('>=3')
2025-07-02 06:41:16.111     def test_1(act: Action):
2025-07-02 06:41:16.111         act.expected_stdout = expected_stdout
2025-07-02 06:41:16.111         act.execute()
2025-07-02 06:41:16.111 >       assert act.clean_stdout == act.clean_expected_stdout
2025-07-02 06:41:16.111
2025-07-02 06:41:16.111 tests\bugs\core_2969_test.py:1211:
2025-07-02 06:41:16.111 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.111
2025-07-02 06:41:16.111 ops = ('==',), results = (False,)
2025-07-02 06:41:16.111 expls = ('%(py2)s\n{%(py2)s = %(py0)s.clean_stdout\n} == %(py6)s\n{%(py6)s = %(py4)s.clean_expected_stdout\n}',)
2025-07-02 06:41:16.111 each_obj = ('WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1var...yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy')
2025-07-02 06:41:16.111
2025-07-02 06:41:16.111     def _call_reprcompare(
2025-07-02 06:41:16.111         ops: Sequence[str],
2025-07-02 06:41:16.111         results: Sequence[bool],
2025-07-02 06:41:16.111         expls: Sequence[str],
2025-07-02 06:41:16.111         each_obj: Sequence[object],
2025-07-02 06:41:16.111     ) -> str:
2025-07-02 06:41:16.111         for i, res, expl in zip(range(len(ops)), results, expls):
2025-07-02 06:41:16.112             try:
2025-07-02 06:41:16.112                 done = not res
2025-07-02 06:41:16.112             except Exception:
2025-07-02 06:41:16.112                 done = True
2025-07-02 06:41:16.112             if done:
2025-07-02 06:41:16.112                 break
2025-07-02 06:41:16.112         if util._reprcompare is not None:
2025-07-02 06:41:16.112 >           custom = util._reprcompare(ops[i], each_obj[i], each_obj[i + 1])
2025-07-02 06:41:16.112
2025-07-02 06:41:16.112 C:\Python3x\Lib\site-packages\_pytest\assertion\rewrite.py:499:
2025-07-02 06:41:16.112 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.112
2025-07-02 06:41:16.112 op = '=='
2025-07-02 06:41:16.112 left = 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1var_...    yyy\n1var_997                        yyy\n1var_998                        yyy\n1var_999                        yyy'
2025-07-02 06:41:16.112 right = 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1 var... yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy'
2025-07-02 06:41:16.112
2025-07-02 06:41:16.112     def callbinrepr(op, left: object, right: object) -> Optional[str]:
2025-07-02 06:41:16.112         """Call the pytest_assertrepr_compare hook and prepare the result.
2025-07-02 06:41:16.113
2025-07-02 06:41:16.113         This uses the first result from the hook and then ensures the
2025-07-02 06:41:16.113         following:
2025-07-02 06:41:16.113         * Overly verbose explanations are truncated unless configured otherwise
2025-07-02 06:41:16.113           (eg. if running in verbose mode).
2025-07-02 06:41:16.113         * Embedded newlines are escaped to help util.format_explanation()
2025-07-02 06:41:16.113           later.
2025-07-02 06:41:16.113         * If the rewrite mode is used embedded %-characters are replaced
2025-07-02 06:41:16.113           to protect later % formatting.
2025-07-02 06:41:16.113
2025-07-02 06:41:16.113         The result can be formatted by util.format_explanation() for
2025-07-02 06:41:16.113         pretty printing.
2025-07-02 06:41:16.113         """
2025-07-02 06:41:16.113 >       hook_result = ihook.pytest_assertrepr_compare(
2025-07-02 06:41:16.113             config=item.config, op=op, left=left, right=right
2025-07-02 06:41:16.113         )
2025-07-02 06:41:16.113
2025-07-02 06:41:16.113 C:\Python3x\Lib\site-packages\_pytest\assertion\__init__.py:141:
2025-07-02 06:41:16.113 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.114
2025-07-02 06:41:16.114 self = <HookCaller 'pytest_assertrepr_compare'>
2025-07-02 06:41:16.114 kwargs = {'config': <_pytest.config.Config object at [hex]>, 'left': 'WAS_OVERWRITTEN CTX_KEY                     ...yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy'}
2025-07-02 06:41:16.114 firstresult = False
2025-07-02 06:41:16.114
2025-07-02 06:41:16.114     def __call__(self, **kwargs: object) -> Any:
2025-07-02 06:41:16.114         """Call the hook.
2025-07-02 06:41:16.114
2025-07-02 06:41:16.114         Only accepts keyword arguments, which should match the hook
2025-07-02 06:41:16.114         specification.
2025-07-02 06:41:16.114
2025-07-02 06:41:16.114         Returns the result(s) of calling all registered plugins, see
2025-07-02 06:41:16.114         :ref:`calling`.
2025-07-02 06:41:16.114         """
2025-07-02 06:41:16.114         assert (
2025-07-02 06:41:16.114             not self.is_historic()
2025-07-02 06:41:16.114         ), "Cannot directly call a historic hook - use call_historic instead."
2025-07-02 06:41:16.114         self._verify_all_args_are_provided(kwargs)
2025-07-02 06:41:16.114         firstresult = self.spec.opts.get("firstresult", False) if self.spec else False
2025-07-02 06:41:16.114         # Copy because plugins may register other plugins during iteration (#438).
2025-07-02 06:41:16.115 >       return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
2025-07-02 06:41:16.115
2025-07-02 06:41:16.115 C:\Python3x\Lib\site-packages\pluggy\_hooks.py:501:
2025-07-02 06:41:16.115 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.115
2025-07-02 06:41:16.115 self = <_pytest.config.PytestPluginManager object at [hex]>
2025-07-02 06:41:16.115 hook_name = 'pytest_assertrepr_compare'
2025-07-02 06:41:16.115 methods = [<HookImpl plugin_name='assertion', plugin=<module '_pytest.assertion' from 'C:\\Python3x\\Lib\\site-packages\\_pytest...plugin_name='firebird', plugin=<module 'firebird.qa.plugin' from 'H:\\QA\\firebird-qa\\src\\firebird\\qa\\plugin.py'>>]
2025-07-02 06:41:16.115 kwargs = {'config': <_pytest.config.Config object at [hex]>, 'left': 'WAS_OVERWRITTEN CTX_KEY                     ...yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy'}
2025-07-02 06:41:16.115 firstresult = False
2025-07-02 06:41:16.115
2025-07-02 06:41:16.115     def _hookexec(
2025-07-02 06:41:16.115         self,
2025-07-02 06:41:16.115         hook_name: str,
2025-07-02 06:41:16.115         methods: Sequence[HookImpl],
2025-07-02 06:41:16.115         kwargs: Mapping[str, object],
2025-07-02 06:41:16.115         firstresult: bool,
2025-07-02 06:41:16.115     ) -> object | list[object]:
2025-07-02 06:41:16.115         # called from all hookcaller instances.
2025-07-02 06:41:16.116         # enable_tracing will set its own wrapping function at self._inner_hookexec
2025-07-02 06:41:16.116 >       return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
2025-07-02 06:41:16.116
2025-07-02 06:41:16.116 C:\Python3x\Lib\site-packages\pluggy\_manager.py:119:
2025-07-02 06:41:16.116 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.116
2025-07-02 06:41:16.116 config = <_pytest.config.Config object at [hex]>, op = '=='
2025-07-02 06:41:16.116 left = 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1var_...    yyy\n1var_997                        yyy\n1var_998                        yyy\n1var_999                        yyy'
2025-07-02 06:41:16.116 right = 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1 var... yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy'
2025-07-02 06:41:16.116
2025-07-02 06:41:16.116     def pytest_assertrepr_compare(config: Config, op: str, left: object, right: object) -> Optional[List[str]]:
2025-07-02 06:41:16.116         """Returns explanation for comparisons in failing assert expressions.
2025-07-02 06:41:16.116
2025-07-02 06:41:16.116         If both objects are `str`, uses `difflib.ndiff` to provide explanation.
2025-07-02 06:41:16.116         """
2025-07-02 06:41:16.116         if isinstance(left, str) and isinstance(right, str) and op == "==":
2025-07-02 06:41:16.116             # 16.11.2023, pzotov: we have to put empty string at the beginning of each comparing lists.
2025-07-02 06:41:16.116             # Otherwise first diff will be at the same line as 'assert' phrase, which causes readability be poor.
2025-07-02 06:41:16.116             #
2025-07-02 06:41:16.117             left_lines = ['']
2025-07-02 06:41:16.117             left_lines.extend(left.splitlines())
2025-07-02 06:41:16.117             right_lines = ['']
2025-07-02 06:41:16.117             right_lines.extend(right.splitlines())
2025-07-02 06:41:16.117
2025-07-02 06:41:16.117             # 16.11.2023, pzotov
2025-07-02 06:41:16.117             # ndiff output must be interpreted as following:
2025-07-02 06:41:16.117             #     * "E     - <some text>" ==> MISSED line (it was in EXPECTED text but absent in actual one).
2025-07-02 06:41:16.117             #     * "E     + <some_text>" ==> EXCESSIVE line (it is not in EXPECTED text but did appear in actual).
2025-07-02 06:41:16.117             # But for QA-purposes, this output must answer the question:
2025-07-02 06:41:16.117             #     "what must be changed in ACTUAL output so that it became equal to EXPECTED"
2025-07-02 06:41:16.117             #     (i.e. how to "REVERT" actual back to expected).
2025-07-02 06:41:16.117             # In order to see such result, we have to specify 'right_lines' to the 1st argument that is passed to ndiff().
2025-07-02 06:41:16.117             # ::: NB :::
2025-07-02 06:41:16.117             # We assume that all tests are written so that ACTUAL output is left side in 'assert' statement and EXPECTED
2025-07-02 06:41:16.117             # is right side, e.g: assert act.clean_stdout == act.clean_expected_stdout
2025-07-02 06:41:16.117             # This requirement is CRUCIAL if we use ndiff() instead of default pytest comparison method!
2025-07-02 06:41:16.117             #
2025-07-02 06:41:16.118 >           return list(ndiff(right_lines, left_lines))
2025-07-02 06:41:16.118
2025-07-02 06:41:16.118 src\firebird\qa\plugin.py:608:
2025-07-02 06:41:16.118 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.118
2025-07-02 06:41:16.118 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.118 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.118 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.118
2025-07-02 06:41:16.118     def compare(self, a, b):
2025-07-02 06:41:16.118         r"""
2025-07-02 06:41:16.118         Compare two sequences of lines; generate the resulting delta.
2025-07-02 06:41:16.118
2025-07-02 06:41:16.118         Each sequence must contain individual single-line strings ending with
2025-07-02 06:41:16.118         newlines. Such sequences can be obtained from the `readlines()` method
2025-07-02 06:41:16.118         of file-like objects.  The delta generated also consists of newline-
2025-07-02 06:41:16.118         terminated strings, ready to be printed as-is via the writelines()
2025-07-02 06:41:16.118         method of a file-like object.
2025-07-02 06:41:16.118
2025-07-02 06:41:16.119         Example:
2025-07-02 06:41:16.119
2025-07-02 06:41:16.119         >>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True),
2025-07-02 06:41:16.119         ...                                'ore\ntree\nemu\n'.splitlines(True))),
2025-07-02 06:41:16.119         ...       end="")
2025-07-02 06:41:16.119         - one
2025-07-02 06:41:16.119         + ore
2025-07-02 06:41:16.119         - two
2025-07-02 06:41:16.119         - three
2025-07-02 06:41:16.119         + tree
2025-07-02 06:41:16.119         + emu
2025-07-02 06:41:16.119         """
2025-07-02 06:41:16.119
2025-07-02 06:41:16.119         cruncher = SequenceMatcher(self.linejunk, a, b)
2025-07-02 06:41:16.119         for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
2025-07-02 06:41:16.119             if tag == 'replace':
2025-07-02 06:41:16.119                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.120             elif tag == 'delete':
2025-07-02 06:41:16.120                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.120             elif tag == 'insert':
2025-07-02 06:41:16.120                 g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.120             elif tag == 'equal':
2025-07-02 06:41:16.120                 g = self._dump(' ', a, alo, ahi)
2025-07-02 06:41:16.120             else:
2025-07-02 06:41:16.120                 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.120
2025-07-02 06:41:16.120 >           yield from g
2025-07-02 06:41:16.120
2025-07-02 06:41:16.120 C:\Python3x\Lib\difflib.py:872:
2025-07-02 06:41:16.120 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.120
2025-07-02 06:41:16.120 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.120 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.120 alo = 3, ahi = 1101
2025-07-02 06:41:16.120 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.120 blo = 3, bhi = 1101
2025-07-02 06:41:16.121
2025-07-02 06:41:16.121     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.121         r"""
2025-07-02 06:41:16.121         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.121         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.121         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.121         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.121
2025-07-02 06:41:16.121         Example:
2025-07-02 06:41:16.121
2025-07-02 06:41:16.121         >>> d = Differ()
2025-07-02 06:41:16.121         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.121         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.121         >>> print(''.join(results), end="")
2025-07-02 06:41:16.121         - abcDefghiJkl
2025-07-02 06:41:16.121         + abcdefGhijkl
2025-07-02 06:41:16.121         """
2025-07-02 06:41:16.121
2025-07-02 06:41:16.122         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.122         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.122         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.122         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.122         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.122
2025-07-02 06:41:16.122         # search for the pair that matches best without being identical
2025-07-02 06:41:16.122         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.122         # on junk -- unless we have to)
2025-07-02 06:41:16.122         for j in range(blo, bhi):
2025-07-02 06:41:16.122             bj = b[j]
2025-07-02 06:41:16.122             cruncher.set_seq2(bj)
2025-07-02 06:41:16.122             for i in range(alo, ahi):
2025-07-02 06:41:16.122                 ai = a[i]
2025-07-02 06:41:16.122                 if ai == bj:
2025-07-02 06:41:16.122                     if eqi is None:
2025-07-02 06:41:16.122                         eqi, eqj = i, j
2025-07-02 06:41:16.122                     continue
2025-07-02 06:41:16.122                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.122                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.123                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.123                 # compares by a factor of 3.
2025-07-02 06:41:16.123                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.123                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.123                 # of the computation is cached by cruncher
2025-07-02 06:41:16.123                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.123                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.123                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.123                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.123         if best_ratio < cutoff:
2025-07-02 06:41:16.123             # no non-identical "pretty close" pair
2025-07-02 06:41:16.123             if eqi is None:
2025-07-02 06:41:16.123                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.123                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.123                 return
2025-07-02 06:41:16.123             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.123             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.123         else:
2025-07-02 06:41:16.123             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.123             eqi = None
2025-07-02 06:41:16.124
2025-07-02 06:41:16.124         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.124         # identical
2025-07-02 06:41:16.124
2025-07-02 06:41:16.124         # pump out diffs from before the synch point
2025-07-02 06:41:16.124         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.124
2025-07-02 06:41:16.124         # do intraline marking on the synch pair
2025-07-02 06:41:16.124         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.124         if eqi is None:
2025-07-02 06:41:16.124             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.124             atags = btags = ""
2025-07-02 06:41:16.124             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.124             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.124                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.124                 if tag == 'replace':
2025-07-02 06:41:16.124                     atags += '^' * la
2025-07-02 06:41:16.124                     btags += '^' * lb
2025-07-02 06:41:16.124                 elif tag == 'delete':
2025-07-02 06:41:16.124                     atags += '-' * la
2025-07-02 06:41:16.125                 elif tag == 'insert':
2025-07-02 06:41:16.125                     btags += '+' * lb
2025-07-02 06:41:16.125                 elif tag == 'equal':
2025-07-02 06:41:16.125                     atags += ' ' * la
2025-07-02 06:41:16.125                     btags += ' ' * lb
2025-07-02 06:41:16.125                 else:
2025-07-02 06:41:16.125                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.125             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.125         else:
2025-07-02 06:41:16.125             # the synch pair is identical
2025-07-02 06:41:16.125             yield '  ' + aelt
2025-07-02 06:41:16.125
2025-07-02 06:41:16.125         # pump out diffs from after the synch point
2025-07-02 06:41:16.125 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.125
2025-07-02 06:41:16.125 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.125 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.125
2025-07-02 06:41:16.125 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.125 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.126 alo = 4, ahi = 1101
2025-07-02 06:41:16.126 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.126 blo = 4, bhi = 1101
2025-07-02 06:41:16.126
2025-07-02 06:41:16.126     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.126         g = []
2025-07-02 06:41:16.126         if alo < ahi:
2025-07-02 06:41:16.126             if blo < bhi:
2025-07-02 06:41:16.126                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.126             else:
2025-07-02 06:41:16.126                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.126         elif blo < bhi:
2025-07-02 06:41:16.126             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.126
2025-07-02 06:41:16.126 >       yield from g
2025-07-02 06:41:16.126
2025-07-02 06:41:16.126 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.126 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.127
2025-07-02 06:41:16.127 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.127 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.127 alo = 4, ahi = 1101
2025-07-02 06:41:16.127 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.127 blo = 4, bhi = 1101
2025-07-02 06:41:16.127
2025-07-02 06:41:16.127     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.127         r"""
2025-07-02 06:41:16.127         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.127         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.127         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.127         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.127
2025-07-02 06:41:16.127         Example:
2025-07-02 06:41:16.127
2025-07-02 06:41:16.127         >>> d = Differ()
2025-07-02 06:41:16.127         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.127         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.128         >>> print(''.join(results), end="")
2025-07-02 06:41:16.128         - abcDefghiJkl
2025-07-02 06:41:16.128         + abcdefGhijkl
2025-07-02 06:41:16.128         """
2025-07-02 06:41:16.128
2025-07-02 06:41:16.128         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.128         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.128         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.128         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.128         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.128
2025-07-02 06:41:16.128         # search for the pair that matches best without being identical
2025-07-02 06:41:16.128         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.128         # on junk -- unless we have to)
2025-07-02 06:41:16.128         for j in range(blo, bhi):
2025-07-02 06:41:16.128             bj = b[j]
2025-07-02 06:41:16.129             cruncher.set_seq2(bj)
2025-07-02 06:41:16.129             for i in range(alo, ahi):
2025-07-02 06:41:16.129                 ai = a[i]
2025-07-02 06:41:16.129                 if ai == bj:
2025-07-02 06:41:16.129                     if eqi is None:
2025-07-02 06:41:16.129                         eqi, eqj = i, j
2025-07-02 06:41:16.129                     continue
2025-07-02 06:41:16.129                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.129                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.129                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.129                 # compares by a factor of 3.
2025-07-02 06:41:16.129                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.129                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.129                 # of the computation is cached by cruncher
2025-07-02 06:41:16.129                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.129                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.129                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.129                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.129         if best_ratio < cutoff:
2025-07-02 06:41:16.130             # no non-identical "pretty close" pair
2025-07-02 06:41:16.130             if eqi is None:
2025-07-02 06:41:16.130                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.130                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.130                 return
2025-07-02 06:41:16.130             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.130             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.130         else:
2025-07-02 06:41:16.130             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.130             eqi = None
2025-07-02 06:41:16.130
2025-07-02 06:41:16.130         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.130         # identical
2025-07-02 06:41:16.130
2025-07-02 06:41:16.130         # pump out diffs from before the synch point
2025-07-02 06:41:16.130         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.130
2025-07-02 06:41:16.130         # do intraline marking on the synch pair
2025-07-02 06:41:16.130         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.130         if eqi is None:
2025-07-02 06:41:16.130             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.131             atags = btags = ""
2025-07-02 06:41:16.131             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.131             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.131                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.131                 if tag == 'replace':
2025-07-02 06:41:16.131                     atags += '^' * la
2025-07-02 06:41:16.131                     btags += '^' * lb
2025-07-02 06:41:16.131                 elif tag == 'delete':
2025-07-02 06:41:16.131                     atags += '-' * la
2025-07-02 06:41:16.131                 elif tag == 'insert':
2025-07-02 06:41:16.131                     btags += '+' * lb
2025-07-02 06:41:16.131                 elif tag == 'equal':
2025-07-02 06:41:16.131                     atags += ' ' * la
2025-07-02 06:41:16.131                     btags += ' ' * lb
2025-07-02 06:41:16.131                 else:
2025-07-02 06:41:16.131                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.131             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.131         else:
2025-07-02 06:41:16.131             # the synch pair is identical
2025-07-02 06:41:16.131             yield '  ' + aelt
2025-07-02 06:41:16.132
2025-07-02 06:41:16.132         # pump out diffs from after the synch point
2025-07-02 06:41:16.132 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.132
2025-07-02 06:41:16.132 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.132 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.132
2025-07-02 06:41:16.132 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.132 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.132 alo = 5, ahi = 1101
2025-07-02 06:41:16.132 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.132 blo = 5, bhi = 1101
2025-07-02 06:41:16.132
2025-07-02 06:41:16.132     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.132         g = []
2025-07-02 06:41:16.132         if alo < ahi:
2025-07-02 06:41:16.132             if blo < bhi:
2025-07-02 06:41:16.132                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.132             else:
2025-07-02 06:41:16.132                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.133         elif blo < bhi:
2025-07-02 06:41:16.133             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.133
2025-07-02 06:41:16.133 >       yield from g
2025-07-02 06:41:16.133
2025-07-02 06:41:16.133 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.133 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.133
2025-07-02 06:41:16.133 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.133 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.133 alo = 5, ahi = 1101
2025-07-02 06:41:16.133 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.133 blo = 5, bhi = 1101
2025-07-02 06:41:16.133
2025-07-02 06:41:16.133     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.133         r"""
2025-07-02 06:41:16.133         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.133         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.133         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.133         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.134
2025-07-02 06:41:16.134         Example:
2025-07-02 06:41:16.134
2025-07-02 06:41:16.134         >>> d = Differ()
2025-07-02 06:41:16.134         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.134         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.134         >>> print(''.join(results), end="")
2025-07-02 06:41:16.134         - abcDefghiJkl
2025-07-02 06:41:16.134         + abcdefGhijkl
2025-07-02 06:41:16.134         """
2025-07-02 06:41:16.134
2025-07-02 06:41:16.134         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.134         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.134         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.134         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.134         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.134
2025-07-02 06:41:16.134         # search for the pair that matches best without being identical
2025-07-02 06:41:16.135         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.135         # on junk -- unless we have to)
2025-07-02 06:41:16.135         for j in range(blo, bhi):
2025-07-02 06:41:16.135             bj = b[j]
2025-07-02 06:41:16.135             cruncher.set_seq2(bj)
2025-07-02 06:41:16.135             for i in range(alo, ahi):
2025-07-02 06:41:16.135                 ai = a[i]
2025-07-02 06:41:16.135                 if ai == bj:
2025-07-02 06:41:16.135                     if eqi is None:
2025-07-02 06:41:16.135                         eqi, eqj = i, j
2025-07-02 06:41:16.135                     continue
2025-07-02 06:41:16.135                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.135                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.135                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.135                 # compares by a factor of 3.
2025-07-02 06:41:16.135                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.135                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.135                 # of the computation is cached by cruncher
2025-07-02 06:41:16.135                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.136                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.136                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.136                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.136         if best_ratio < cutoff:
2025-07-02 06:41:16.136             # no non-identical "pretty close" pair
2025-07-02 06:41:16.136             if eqi is None:
2025-07-02 06:41:16.136                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.136                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.136                 return
2025-07-02 06:41:16.136             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.136             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.136         else:
2025-07-02 06:41:16.136             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.136             eqi = None
2025-07-02 06:41:16.136
2025-07-02 06:41:16.136         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.136         # identical
2025-07-02 06:41:16.136
2025-07-02 06:41:16.136         # pump out diffs from before the synch point
2025-07-02 06:41:16.136         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.137
2025-07-02 06:41:16.137         # do intraline marking on the synch pair
2025-07-02 06:41:16.137         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.137         if eqi is None:
2025-07-02 06:41:16.137             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.137             atags = btags = ""
2025-07-02 06:41:16.137             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.137             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.137                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.137                 if tag == 'replace':
2025-07-02 06:41:16.137                     atags += '^' * la
2025-07-02 06:41:16.137                     btags += '^' * lb
2025-07-02 06:41:16.137                 elif tag == 'delete':
2025-07-02 06:41:16.137                     atags += '-' * la
2025-07-02 06:41:16.137                 elif tag == 'insert':
2025-07-02 06:41:16.137                     btags += '+' * lb
2025-07-02 06:41:16.137                 elif tag == 'equal':
2025-07-02 06:41:16.137                     atags += ' ' * la
2025-07-02 06:41:16.137                     btags += ' ' * lb
2025-07-02 06:41:16.137                 else:
2025-07-02 06:41:16.138                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.138             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.138         else:
2025-07-02 06:41:16.138             # the synch pair is identical
2025-07-02 06:41:16.138             yield '  ' + aelt
2025-07-02 06:41:16.138
2025-07-02 06:41:16.138         # pump out diffs from after the synch point
2025-07-02 06:41:16.138 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.138
2025-07-02 06:41:16.138 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.138 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.138
2025-07-02 06:41:16.138 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.138 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.138 alo = 6, ahi = 1101
2025-07-02 06:41:16.138 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.138 blo = 6, bhi = 1101
2025-07-02 06:41:16.138
2025-07-02 06:41:16.138     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.138         g = []
2025-07-02 06:41:16.139         if alo < ahi:
2025-07-02 06:41:16.139             if blo < bhi:
2025-07-02 06:41:16.139                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.139             else:
2025-07-02 06:41:16.139                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.139         elif blo < bhi:
2025-07-02 06:41:16.139             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.139
2025-07-02 06:41:16.139 >       yield from g
2025-07-02 06:41:16.139
2025-07-02 06:41:16.139 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.139 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.139
2025-07-02 06:41:16.139 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.139 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.139 alo = 6, ahi = 1101
2025-07-02 06:41:16.139 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.139 blo = 6, bhi = 1101
2025-07-02 06:41:16.139
2025-07-02 06:41:16.139     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.140         r"""
2025-07-02 06:41:16.140         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.140         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.140         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.140         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.140
2025-07-02 06:41:16.140         Example:
2025-07-02 06:41:16.140
2025-07-02 06:41:16.140         >>> d = Differ()
2025-07-02 06:41:16.140         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.140         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.140         >>> print(''.join(results), end="")
2025-07-02 06:41:16.140         - abcDefghiJkl
2025-07-02 06:41:16.140         + abcdefGhijkl
2025-07-02 06:41:16.140         """
2025-07-02 06:41:16.140
2025-07-02 06:41:16.140         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.140         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.140         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.141         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.141         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.141
2025-07-02 06:41:16.141         # search for the pair that matches best without being identical
2025-07-02 06:41:16.141         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.141         # on junk -- unless we have to)
2025-07-02 06:41:16.141         for j in range(blo, bhi):
2025-07-02 06:41:16.141             bj = b[j]
2025-07-02 06:41:16.141             cruncher.set_seq2(bj)
2025-07-02 06:41:16.141             for i in range(alo, ahi):
2025-07-02 06:41:16.141                 ai = a[i]
2025-07-02 06:41:16.141                 if ai == bj:
2025-07-02 06:41:16.141                     if eqi is None:
2025-07-02 06:41:16.141                         eqi, eqj = i, j
2025-07-02 06:41:16.141                     continue
2025-07-02 06:41:16.141                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.141                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.141                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.141                 # compares by a factor of 3.
2025-07-02 06:41:16.141                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.142                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.142                 # of the computation is cached by cruncher
2025-07-02 06:41:16.142                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.142                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.142                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.142                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.142         if best_ratio < cutoff:
2025-07-02 06:41:16.142             # no non-identical "pretty close" pair
2025-07-02 06:41:16.142             if eqi is None:
2025-07-02 06:41:16.142                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.142                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.142                 return
2025-07-02 06:41:16.142             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.142             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.142         else:
2025-07-02 06:41:16.142             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.142             eqi = None
2025-07-02 06:41:16.142
2025-07-02 06:41:16.142         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.143         # identical
2025-07-02 06:41:16.143
2025-07-02 06:41:16.143         # pump out diffs from before the synch point
2025-07-02 06:41:16.143         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.143
2025-07-02 06:41:16.143         # do intraline marking on the synch pair
2025-07-02 06:41:16.143         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.143         if eqi is None:
2025-07-02 06:41:16.143             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.143             atags = btags = ""
2025-07-02 06:41:16.143             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.143             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.143                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.143                 if tag == 'replace':
2025-07-02 06:41:16.143                     atags += '^' * la
2025-07-02 06:41:16.143                     btags += '^' * lb
2025-07-02 06:41:16.143                 elif tag == 'delete':
2025-07-02 06:41:16.143                     atags += '-' * la
2025-07-02 06:41:16.143                 elif tag == 'insert':
2025-07-02 06:41:16.144                     btags += '+' * lb
2025-07-02 06:41:16.144                 elif tag == 'equal':
2025-07-02 06:41:16.144                     atags += ' ' * la
2025-07-02 06:41:16.144                     btags += ' ' * lb
2025-07-02 06:41:16.144                 else:
2025-07-02 06:41:16.144                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.144             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.144         else:
2025-07-02 06:41:16.144             # the synch pair is identical
2025-07-02 06:41:16.144             yield '  ' + aelt
2025-07-02 06:41:16.144
2025-07-02 06:41:16.144         # pump out diffs from after the synch point
2025-07-02 06:41:16.144 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.144
2025-07-02 06:41:16.144 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.144 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.144
2025-07-02 06:41:16.144 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.144 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.145 alo = 7, ahi = 1101
2025-07-02 06:41:16.145 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.145 blo = 7, bhi = 1101
2025-07-02 06:41:16.145
2025-07-02 06:41:16.145     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.145         g = []
2025-07-02 06:41:16.145         if alo < ahi:
2025-07-02 06:41:16.145             if blo < bhi:
2025-07-02 06:41:16.145                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.145             else:
2025-07-02 06:41:16.145                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.145         elif blo < bhi:
2025-07-02 06:41:16.145             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.145
2025-07-02 06:41:16.145 >       yield from g
2025-07-02 06:41:16.145
2025-07-02 06:41:16.145 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.145 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.145
2025-07-02 06:41:16.146 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.146 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.146 alo = 7, ahi = 1101
2025-07-02 06:41:16.146 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.146 blo = 7, bhi = 1101
2025-07-02 06:41:16.146
2025-07-02 06:41:16.146     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.146         r"""
2025-07-02 06:41:16.146         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.146         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.146         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.146         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.146
2025-07-02 06:41:16.146         Example:
2025-07-02 06:41:16.146
2025-07-02 06:41:16.146         >>> d = Differ()
2025-07-02 06:41:16.146         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.146         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.146         >>> print(''.join(results), end="")
2025-07-02 06:41:16.146         - abcDefghiJkl
2025-07-02 06:41:16.147         + abcdefGhijkl
2025-07-02 06:41:16.147         """
2025-07-02 06:41:16.147
2025-07-02 06:41:16.147         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.147         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.147         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.147         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.147         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.147
2025-07-02 06:41:16.147         # search for the pair that matches best without being identical
2025-07-02 06:41:16.147         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.147         # on junk -- unless we have to)
2025-07-02 06:41:16.147         for j in range(blo, bhi):
2025-07-02 06:41:16.147             bj = b[j]
2025-07-02 06:41:16.147             cruncher.set_seq2(bj)
2025-07-02 06:41:16.147             for i in range(alo, ahi):
2025-07-02 06:41:16.147                 ai = a[i]
2025-07-02 06:41:16.147                 if ai == bj:
2025-07-02 06:41:16.147                     if eqi is None:
2025-07-02 06:41:16.148                         eqi, eqj = i, j
2025-07-02 06:41:16.148                     continue
2025-07-02 06:41:16.148                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.148                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.148                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.148                 # compares by a factor of 3.
2025-07-02 06:41:16.148                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.148                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.148                 # of the computation is cached by cruncher
2025-07-02 06:41:16.148                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.148                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.148                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.148                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.148         if best_ratio < cutoff:
2025-07-02 06:41:16.148             # no non-identical "pretty close" pair
2025-07-02 06:41:16.148             if eqi is None:
2025-07-02 06:41:16.148                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.148                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.148                 return
2025-07-02 06:41:16.148             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.149             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.149         else:
2025-07-02 06:41:16.149             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.149             eqi = None
2025-07-02 06:41:16.149
2025-07-02 06:41:16.149         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.149         # identical
2025-07-02 06:41:16.149
2025-07-02 06:41:16.149         # pump out diffs from before the synch point
2025-07-02 06:41:16.149         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.149
2025-07-02 06:41:16.149         # do intraline marking on the synch pair
2025-07-02 06:41:16.149         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.149         if eqi is None:
2025-07-02 06:41:16.149             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.149             atags = btags = ""
2025-07-02 06:41:16.149             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.149             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.149                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.149                 if tag == 'replace':
2025-07-02 06:41:16.150                     atags += '^' * la
2025-07-02 06:41:16.150                     btags += '^' * lb
2025-07-02 06:41:16.150                 elif tag == 'delete':
2025-07-02 06:41:16.150                     atags += '-' * la
2025-07-02 06:41:16.150                 elif tag == 'insert':
2025-07-02 06:41:16.150                     btags += '+' * lb
2025-07-02 06:41:16.150                 elif tag == 'equal':
2025-07-02 06:41:16.150                     atags += ' ' * la
2025-07-02 06:41:16.150                     btags += ' ' * lb
2025-07-02 06:41:16.150                 else:
2025-07-02 06:41:16.150                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.150             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.150         else:
2025-07-02 06:41:16.150             # the synch pair is identical
2025-07-02 06:41:16.150             yield '  ' + aelt
2025-07-02 06:41:16.150
2025-07-02 06:41:16.150         # pump out diffs from after the synch point
2025-07-02 06:41:16.150 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.150
2025-07-02 06:41:16.150 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.150 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.151
2025-07-02 06:41:16.151 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.151 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.151 alo = 8, ahi = 1101
2025-07-02 06:41:16.151 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.151 blo = 8, bhi = 1101
2025-07-02 06:41:16.151
2025-07-02 06:41:16.151     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.151         g = []
2025-07-02 06:41:16.151         if alo < ahi:
2025-07-02 06:41:16.151             if blo < bhi:
2025-07-02 06:41:16.151                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.151             else:
2025-07-02 06:41:16.151                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.151         elif blo < bhi:
2025-07-02 06:41:16.151             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.151
2025-07-02 06:41:16.151 >       yield from g
2025-07-02 06:41:16.151
2025-07-02 06:41:16.151 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.152 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.152
2025-07-02 06:41:16.152 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.152 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.152 alo = 8, ahi = 1101
2025-07-02 06:41:16.152 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.152 blo = 8, bhi = 1101
2025-07-02 06:41:16.152
2025-07-02 06:41:16.152     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.152         r"""
2025-07-02 06:41:16.152         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.152         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.152         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.152         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.152
2025-07-02 06:41:16.152         Example:
2025-07-02 06:41:16.152
2025-07-02 06:41:16.152         >>> d = Differ()
2025-07-02 06:41:16.153         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.153         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.153         >>> print(''.join(results), end="")
2025-07-02 06:41:16.153         - abcDefghiJkl
2025-07-02 06:41:16.153         + abcdefGhijkl
2025-07-02 06:41:16.153         """
2025-07-02 06:41:16.153
2025-07-02 06:41:16.153         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.153         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.153         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.153         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.153         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.153
2025-07-02 06:41:16.153         # search for the pair that matches best without being identical
2025-07-02 06:41:16.153         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.153         # on junk -- unless we have to)
2025-07-02 06:41:16.153         for j in range(blo, bhi):
2025-07-02 06:41:16.154             bj = b[j]
2025-07-02 06:41:16.154             cruncher.set_seq2(bj)
2025-07-02 06:41:16.154             for i in range(alo, ahi):
2025-07-02 06:41:16.154                 ai = a[i]
2025-07-02 06:41:16.154                 if ai == bj:
2025-07-02 06:41:16.154                     if eqi is None:
2025-07-02 06:41:16.154                         eqi, eqj = i, j
2025-07-02 06:41:16.154                     continue
2025-07-02 06:41:16.154                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.154                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.154                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.154                 # compares by a factor of 3.
2025-07-02 06:41:16.154                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.154                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.154                 # of the computation is cached by cruncher
2025-07-02 06:41:16.154                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.154                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.154                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.154                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.155         if best_ratio < cutoff:
2025-07-02 06:41:16.155             # no non-identical "pretty close" pair
2025-07-02 06:41:16.155             if eqi is None:
2025-07-02 06:41:16.155                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.155                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.155                 return
2025-07-02 06:41:16.155             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.155             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.155         else:
2025-07-02 06:41:16.155             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.155             eqi = None
2025-07-02 06:41:16.155
2025-07-02 06:41:16.155         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.155         # identical
2025-07-02 06:41:16.155
2025-07-02 06:41:16.155         # pump out diffs from before the synch point
2025-07-02 06:41:16.155         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.155
2025-07-02 06:41:16.155         # do intraline marking on the synch pair
2025-07-02 06:41:16.155         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.156         if eqi is None:
2025-07-02 06:41:16.156             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.156             atags = btags = ""
2025-07-02 06:41:16.156             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.156             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.156                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.156                 if tag == 'replace':
2025-07-02 06:41:16.156                     atags += '^' * la
2025-07-02 06:41:16.156                     btags += '^' * lb
2025-07-02 06:41:16.156                 elif tag == 'delete':
2025-07-02 06:41:16.156                     atags += '-' * la
2025-07-02 06:41:16.156                 elif tag == 'insert':
2025-07-02 06:41:16.156                     btags += '+' * lb
2025-07-02 06:41:16.156                 elif tag == 'equal':
2025-07-02 06:41:16.156                     atags += ' ' * la
2025-07-02 06:41:16.156                     btags += ' ' * lb
2025-07-02 06:41:16.156                 else:
2025-07-02 06:41:16.156                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.156             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.156         else:
2025-07-02 06:41:16.157             # the synch pair is identical
2025-07-02 06:41:16.157             yield '  ' + aelt
2025-07-02 06:41:16.157
2025-07-02 06:41:16.157         # pump out diffs from after the synch point
2025-07-02 06:41:16.157 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.157
2025-07-02 06:41:16.157 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.157 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.157
2025-07-02 06:41:16.157 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.157 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.157 alo = 9, ahi = 1101
2025-07-02 06:41:16.157 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.157 blo = 9, bhi = 1101
2025-07-02 06:41:16.157
2025-07-02 06:41:16.157     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.157         g = []
2025-07-02 06:41:16.157         if alo < ahi:
2025-07-02 06:41:16.157             if blo < bhi:
2025-07-02 06:41:16.158                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.158             else:
2025-07-02 06:41:16.158                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.158         elif blo < bhi:
2025-07-02 06:41:16.158             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.158
2025-07-02 06:41:16.158 >       yield from g
2025-07-02 06:41:16.158
2025-07-02 06:41:16.158 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.158 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.158
2025-07-02 06:41:16.158 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.158 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.158 alo = 9, ahi = 1101
2025-07-02 06:41:16.158 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.158 blo = 9, bhi = 1101
2025-07-02 06:41:16.158
2025-07-02 06:41:16.158     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.158         r"""
2025-07-02 06:41:16.158         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.159         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.159         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.159         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.159
2025-07-02 06:41:16.159         Example:
2025-07-02 06:41:16.159
2025-07-02 06:41:16.159         >>> d = Differ()
2025-07-02 06:41:16.159         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.159         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.159         >>> print(''.join(results), end="")
2025-07-02 06:41:16.159         - abcDefghiJkl
2025-07-02 06:41:16.159         + abcdefGhijkl
2025-07-02 06:41:16.159         """
2025-07-02 06:41:16.159
2025-07-02 06:41:16.159         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.159         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.159         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.160         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.160         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.160
2025-07-02 06:41:16.160         # search for the pair that matches best without being identical
2025-07-02 06:41:16.160         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.160         # on junk -- unless we have to)
2025-07-02 06:41:16.160         for j in range(blo, bhi):
2025-07-02 06:41:16.160             bj = b[j]
2025-07-02 06:41:16.160             cruncher.set_seq2(bj)
2025-07-02 06:41:16.160             for i in range(alo, ahi):
2025-07-02 06:41:16.160                 ai = a[i]
2025-07-02 06:41:16.160                 if ai == bj:
2025-07-02 06:41:16.160                     if eqi is None:
2025-07-02 06:41:16.160                         eqi, eqj = i, j
2025-07-02 06:41:16.160                     continue
2025-07-02 06:41:16.160                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.160                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.160                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.160                 # compares by a factor of 3.
2025-07-02 06:41:16.161                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.161                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.161                 # of the computation is cached by cruncher
2025-07-02 06:41:16.161                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.161                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.161                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.161                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.161         if best_ratio < cutoff:
2025-07-02 06:41:16.161             # no non-identical "pretty close" pair
2025-07-02 06:41:16.161             if eqi is None:
2025-07-02 06:41:16.161                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.161                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.161                 return
2025-07-02 06:41:16.161             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.161             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.161         else:
2025-07-02 06:41:16.161             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.161             eqi = None
2025-07-02 06:41:16.162
2025-07-02 06:41:16.162         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.162         # identical
2025-07-02 06:41:16.162
2025-07-02 06:41:16.162         # pump out diffs from before the synch point
2025-07-02 06:41:16.162         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.162
2025-07-02 06:41:16.162         # do intraline marking on the synch pair
2025-07-02 06:41:16.162         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.162         if eqi is None:
2025-07-02 06:41:16.162             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.162             atags = btags = ""
2025-07-02 06:41:16.162             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.162             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.162                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.162                 if tag == 'replace':
2025-07-02 06:41:16.162                     atags += '^' * la
2025-07-02 06:41:16.162                     btags += '^' * lb
2025-07-02 06:41:16.162                 elif tag == 'delete':
2025-07-02 06:41:16.162                     atags += '-' * la
2025-07-02 06:41:16.163                 elif tag == 'insert':
2025-07-02 06:41:16.163                     btags += '+' * lb
2025-07-02 06:41:16.163                 elif tag == 'equal':
2025-07-02 06:41:16.163                     atags += ' ' * la
2025-07-02 06:41:16.163                     btags += ' ' * lb
2025-07-02 06:41:16.163                 else:
2025-07-02 06:41:16.163                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.163             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.163         else:
2025-07-02 06:41:16.163             # the synch pair is identical
2025-07-02 06:41:16.163             yield '  ' + aelt
2025-07-02 06:41:16.163
2025-07-02 06:41:16.163         # pump out diffs from after the synch point
2025-07-02 06:41:16.163 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.163
2025-07-02 06:41:16.163 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.163 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.163
2025-07-02 06:41:16.163 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.163 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.164 alo = 10, ahi = 1101
2025-07-02 06:41:16.164 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.164 blo = 10, bhi = 1101
2025-07-02 06:41:16.164
2025-07-02 06:41:16.164     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.164         g = []
2025-07-02 06:41:16.164         if alo < ahi:
2025-07-02 06:41:16.164             if blo < bhi:
2025-07-02 06:41:16.164                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.164             else:
2025-07-02 06:41:16.164                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.164         elif blo < bhi:
2025-07-02 06:41:16.164             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.164
2025-07-02 06:41:16.164 >       yield from g
2025-07-02 06:41:16.164
2025-07-02 06:41:16.164 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.164 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.164
2025-07-02 06:41:16.165 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.165 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.165 alo = 10, ahi = 1101
2025-07-02 06:41:16.165 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.165 blo = 10, bhi = 1101
2025-07-02 06:41:16.165
2025-07-02 06:41:16.165     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.165         r"""
2025-07-02 06:41:16.165         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.165         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.165         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.165         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.165
2025-07-02 06:41:16.165         Example:
2025-07-02 06:41:16.165
2025-07-02 06:41:16.165         >>> d = Differ()
2025-07-02 06:41:16.165         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.165         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.165         >>> print(''.join(results), end="")
2025-07-02 06:41:16.166         - abcDefghiJkl
2025-07-02 06:41:16.166         + abcdefGhijkl
2025-07-02 06:41:16.166         """
2025-07-02 06:41:16.166
2025-07-02 06:41:16.166         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.166         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.166         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.166         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.166         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.166
2025-07-02 06:41:16.166         # search for the pair that matches best without being identical
2025-07-02 06:41:16.166         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.166         # on junk -- unless we have to)
2025-07-02 06:41:16.166         for j in range(blo, bhi):
2025-07-02 06:41:16.166             bj = b[j]
2025-07-02 06:41:16.166             cruncher.set_seq2(bj)
2025-07-02 06:41:16.166             for i in range(alo, ahi):
2025-07-02 06:41:16.166                 ai = a[i]
2025-07-02 06:41:16.167                 if ai == bj:
2025-07-02 06:41:16.167                     if eqi is None:
2025-07-02 06:41:16.167                         eqi, eqj = i, j
2025-07-02 06:41:16.167                     continue
2025-07-02 06:41:16.167                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.167                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.167                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.167                 # compares by a factor of 3.
2025-07-02 06:41:16.167                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.167                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.167                 # of the computation is cached by cruncher
2025-07-02 06:41:16.167                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.167                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.167                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.167                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.167         if best_ratio < cutoff:
2025-07-02 06:41:16.167             # no non-identical "pretty close" pair
2025-07-02 06:41:16.167             if eqi is None:
2025-07-02 06:41:16.167                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.167                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.168                 return
2025-07-02 06:41:16.168             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.168             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.168         else:
2025-07-02 06:41:16.168             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.168             eqi = None
2025-07-02 06:41:16.168
2025-07-02 06:41:16.168         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.168         # identical
2025-07-02 06:41:16.168
2025-07-02 06:41:16.168         # pump out diffs from before the synch point
2025-07-02 06:41:16.168         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.168
2025-07-02 06:41:16.168         # do intraline marking on the synch pair
2025-07-02 06:41:16.168         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.168         if eqi is None:
2025-07-02 06:41:16.168             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.168             atags = btags = ""
2025-07-02 06:41:16.168             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.169             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.169                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.169                 if tag == 'replace':
2025-07-02 06:41:16.169                     atags += '^' * la
2025-07-02 06:41:16.169                     btags += '^' * lb
2025-07-02 06:41:16.169                 elif tag == 'delete':
2025-07-02 06:41:16.169                     atags += '-' * la
2025-07-02 06:41:16.169                 elif tag == 'insert':
2025-07-02 06:41:16.169                     btags += '+' * lb
2025-07-02 06:41:16.169                 elif tag == 'equal':
2025-07-02 06:41:16.169                     atags += ' ' * la
2025-07-02 06:41:16.169                     btags += ' ' * lb
2025-07-02 06:41:16.169                 else:
2025-07-02 06:41:16.169                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.169             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.169         else:
2025-07-02 06:41:16.169             # the synch pair is identical
2025-07-02 06:41:16.169             yield '  ' + aelt
2025-07-02 06:41:16.169
2025-07-02 06:41:16.169         # pump out diffs from after the synch point
2025-07-02 06:41:16.170 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.170
2025-07-02 06:41:16.170 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.170 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.170
2025-07-02 06:41:16.170 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.170 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.170 alo = 11, ahi = 1101
2025-07-02 06:41:16.170 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.170 blo = 11, bhi = 1101
2025-07-02 06:41:16.170
2025-07-02 06:41:16.170     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.170         g = []
2025-07-02 06:41:16.170         if alo < ahi:
2025-07-02 06:41:16.170             if blo < bhi:
2025-07-02 06:41:16.170                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.170             else:
2025-07-02 06:41:16.170                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.171         elif blo < bhi:
2025-07-02 06:41:16.171             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.171
2025-07-02 06:41:16.171 >       yield from g
2025-07-02 06:41:16.171
2025-07-02 06:41:16.171 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.171 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.171
2025-07-02 06:41:16.171 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.171 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.171 alo = 11, ahi = 1101
2025-07-02 06:41:16.171 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.171 blo = 11, bhi = 1101
2025-07-02 06:41:16.171
2025-07-02 06:41:16.171     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.171         r"""
2025-07-02 06:41:16.171         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.171         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.171         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.172         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.172
2025-07-02 06:41:16.172         Example:
2025-07-02 06:41:16.172
2025-07-02 06:41:16.172         >>> d = Differ()
2025-07-02 06:41:16.172         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.172         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.172         >>> print(''.join(results), end="")
2025-07-02 06:41:16.172         - abcDefghiJkl
2025-07-02 06:41:16.172         + abcdefGhijkl
2025-07-02 06:41:16.172         """
2025-07-02 06:41:16.172
2025-07-02 06:41:16.172         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.172         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.172         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.172         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.172         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.172
2025-07-02 06:41:16.173         # search for the pair that matches best without being identical
2025-07-02 06:41:16.173         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.173         # on junk -- unless we have to)
2025-07-02 06:41:16.173         for j in range(blo, bhi):
2025-07-02 06:41:16.173             bj = b[j]
2025-07-02 06:41:16.173             cruncher.set_seq2(bj)
2025-07-02 06:41:16.173             for i in range(alo, ahi):
2025-07-02 06:41:16.173                 ai = a[i]
2025-07-02 06:41:16.173                 if ai == bj:
2025-07-02 06:41:16.173                     if eqi is None:
2025-07-02 06:41:16.173                         eqi, eqj = i, j
2025-07-02 06:41:16.173                     continue
2025-07-02 06:41:16.173                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.173                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.173                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.173                 # compares by a factor of 3.
2025-07-02 06:41:16.173                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.173                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.173                 # of the computation is cached by cruncher
2025-07-02 06:41:16.173                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.174                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.174                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.174                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.174         if best_ratio < cutoff:
2025-07-02 06:41:16.174             # no non-identical "pretty close" pair
2025-07-02 06:41:16.174             if eqi is None:
2025-07-02 06:41:16.174                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.174                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.174                 return
2025-07-02 06:41:16.174             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.174             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.174         else:
2025-07-02 06:41:16.174             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.174             eqi = None
2025-07-02 06:41:16.174
2025-07-02 06:41:16.174         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.174         # identical
2025-07-02 06:41:16.174
2025-07-02 06:41:16.174         # pump out diffs from before the synch point
2025-07-02 06:41:16.175         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.175
2025-07-02 06:41:16.175         # do intraline marking on the synch pair
2025-07-02 06:41:16.175         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.175         if eqi is None:
2025-07-02 06:41:16.175             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.175             atags = btags = ""
2025-07-02 06:41:16.175             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.175             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.175                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.175                 if tag == 'replace':
2025-07-02 06:41:16.175                     atags += '^' * la
2025-07-02 06:41:16.175                     btags += '^' * lb
2025-07-02 06:41:16.175                 elif tag == 'delete':
2025-07-02 06:41:16.175                     atags += '-' * la
2025-07-02 06:41:16.175                 elif tag == 'insert':
2025-07-02 06:41:16.175                     btags += '+' * lb
2025-07-02 06:41:16.175                 elif tag == 'equal':
2025-07-02 06:41:16.175                     atags += ' ' * la
2025-07-02 06:41:16.175                     btags += ' ' * lb
2025-07-02 06:41:16.176                 else:
2025-07-02 06:41:16.176                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.176             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.176         else:
2025-07-02 06:41:16.176             # the synch pair is identical
2025-07-02 06:41:16.176             yield '  ' + aelt
2025-07-02 06:41:16.176
2025-07-02 06:41:16.176         # pump out diffs from after the synch point
2025-07-02 06:41:16.176 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.176
2025-07-02 06:41:16.176 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.176 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.176
2025-07-02 06:41:16.176 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.176 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.176 alo = 12, ahi = 1101
2025-07-02 06:41:16.176 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.176 blo = 12, bhi = 1101
2025-07-02 06:41:16.176
2025-07-02 06:41:16.177     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.177         g = []
2025-07-02 06:41:16.177         if alo < ahi:
2025-07-02 06:41:16.177             if blo < bhi:
2025-07-02 06:41:16.177                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.177             else:
2025-07-02 06:41:16.177                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.177         elif blo < bhi:
2025-07-02 06:41:16.177             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.177
2025-07-02 06:41:16.177 >       yield from g
2025-07-02 06:41:16.177
2025-07-02 06:41:16.177 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.177 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.177
2025-07-02 06:41:16.177 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.177 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.177 alo = 12, ahi = 1101
2025-07-02 06:41:16.177 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.177 blo = 12, bhi = 1101
2025-07-02 06:41:16.178
2025-07-02 06:41:16.178     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.178         r"""
2025-07-02 06:41:16.178         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.178         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.178         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.178         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.178
2025-07-02 06:41:16.178         Example:
2025-07-02 06:41:16.178
2025-07-02 06:41:16.178         >>> d = Differ()
2025-07-02 06:41:16.178         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.178         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.178         >>> print(''.join(results), end="")
2025-07-02 06:41:16.178         - abcDefghiJkl
2025-07-02 06:41:16.178         + abcdefGhijkl
2025-07-02 06:41:16.178         """
2025-07-02 06:41:16.179
2025-07-02 06:41:16.179         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.179         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.179         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.179         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.179         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.179
2025-07-02 06:41:16.179         # search for the pair that matches best without being identical
2025-07-02 06:41:16.179         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.179         # on junk -- unless we have to)
2025-07-02 06:41:16.179         for j in range(blo, bhi):
2025-07-02 06:41:16.179             bj = b[j]
2025-07-02 06:41:16.179             cruncher.set_seq2(bj)
2025-07-02 06:41:16.179             for i in range(alo, ahi):
2025-07-02 06:41:16.179                 ai = a[i]
2025-07-02 06:41:16.179                 if ai == bj:
2025-07-02 06:41:16.179                     if eqi is None:
2025-07-02 06:41:16.179                         eqi, eqj = i, j
2025-07-02 06:41:16.179                     continue
2025-07-02 06:41:16.180                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.180                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.180                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.180                 # compares by a factor of 3.
2025-07-02 06:41:16.180                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.180                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.180                 # of the computation is cached by cruncher
2025-07-02 06:41:16.180                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.180                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.180                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.180                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.180         if best_ratio < cutoff:
2025-07-02 06:41:16.180             # no non-identical "pretty close" pair
2025-07-02 06:41:16.180             if eqi is None:
2025-07-02 06:41:16.180                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.180                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.180                 return
2025-07-02 06:41:16.180             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.180             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.180         else:
2025-07-02 06:41:16.181             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.181             eqi = None
2025-07-02 06:41:16.181
2025-07-02 06:41:16.181         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.181         # identical
2025-07-02 06:41:16.181
2025-07-02 06:41:16.181         # pump out diffs from before the synch point
2025-07-02 06:41:16.181         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.181
2025-07-02 06:41:16.181         # do intraline marking on the synch pair
2025-07-02 06:41:16.181         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.181         if eqi is None:
2025-07-02 06:41:16.181             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.181             atags = btags = ""
2025-07-02 06:41:16.181             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.181             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.181                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.181                 if tag == 'replace':
2025-07-02 06:41:16.181                     atags += '^' * la
2025-07-02 06:41:16.181                     btags += '^' * lb
2025-07-02 06:41:16.182                 elif tag == 'delete':
2025-07-02 06:41:16.182                     atags += '-' * la
2025-07-02 06:41:16.182                 elif tag == 'insert':
2025-07-02 06:41:16.182                     btags += '+' * lb
2025-07-02 06:41:16.182                 elif tag == 'equal':
2025-07-02 06:41:16.182                     atags += ' ' * la
2025-07-02 06:41:16.182                     btags += ' ' * lb
2025-07-02 06:41:16.182                 else:
2025-07-02 06:41:16.182                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.182             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.182         else:
2025-07-02 06:41:16.182             # the synch pair is identical
2025-07-02 06:41:16.182             yield '  ' + aelt
2025-07-02 06:41:16.182
2025-07-02 06:41:16.182         # pump out diffs from after the synch point
2025-07-02 06:41:16.182 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.182
2025-07-02 06:41:16.182 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.182 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.182
2025-07-02 06:41:16.182 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.183 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.183 alo = 13, ahi = 1101
2025-07-02 06:41:16.183 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.183 blo = 13, bhi = 1101
2025-07-02 06:41:16.183
2025-07-02 06:41:16.183     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.183         g = []
2025-07-02 06:41:16.183         if alo < ahi:
2025-07-02 06:41:16.183             if blo < bhi:
2025-07-02 06:41:16.183                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.183             else:
2025-07-02 06:41:16.183                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.183         elif blo < bhi:
2025-07-02 06:41:16.183             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.183
2025-07-02 06:41:16.183 >       yield from g
2025-07-02 06:41:16.183
2025-07-02 06:41:16.183 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.183 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.183
2025-07-02 06:41:16.184 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.184 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.184 alo = 13, ahi = 1101
2025-07-02 06:41:16.184 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.184 blo = 13, bhi = 1101
2025-07-02 06:41:16.184
2025-07-02 06:41:16.184     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.184         r"""
2025-07-02 06:41:16.184         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.184         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.184         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.184         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.184
2025-07-02 06:41:16.184         Example:
2025-07-02 06:41:16.184
2025-07-02 06:41:16.184         >>> d = Differ()
2025-07-02 06:41:16.184         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.184         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.184         >>> print(''.join(results), end="")
2025-07-02 06:41:16.184         - abcDefghiJkl
2025-07-02 06:41:16.185         + abcdefGhijkl
2025-07-02 06:41:16.185         """
2025-07-02 06:41:16.185
2025-07-02 06:41:16.185         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.185         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.185         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.185         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.185         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.185
2025-07-02 06:41:16.185         # search for the pair that matches best without being identical
2025-07-02 06:41:16.185         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.185         # on junk -- unless we have to)
2025-07-02 06:41:16.185         for j in range(blo, bhi):
2025-07-02 06:41:16.185             bj = b[j]
2025-07-02 06:41:16.185             cruncher.set_seq2(bj)
2025-07-02 06:41:16.185             for i in range(alo, ahi):
2025-07-02 06:41:16.185                 ai = a[i]
2025-07-02 06:41:16.185                 if ai == bj:
2025-07-02 06:41:16.186                     if eqi is None:
2025-07-02 06:41:16.186                         eqi, eqj = i, j
2025-07-02 06:41:16.186                     continue
2025-07-02 06:41:16.186                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.186                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.186                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.186                 # compares by a factor of 3.
2025-07-02 06:41:16.186                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.186                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.186                 # of the computation is cached by cruncher
2025-07-02 06:41:16.186                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.186                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.186                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.186                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.186         if best_ratio < cutoff:
2025-07-02 06:41:16.186             # no non-identical "pretty close" pair
2025-07-02 06:41:16.186             if eqi is None:
2025-07-02 06:41:16.186                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.186                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.186                 return
2025-07-02 06:41:16.186             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.187             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.187         else:
2025-07-02 06:41:16.187             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.187             eqi = None
2025-07-02 06:41:16.187
2025-07-02 06:41:16.187         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.187         # identical
2025-07-02 06:41:16.187
2025-07-02 06:41:16.187         # pump out diffs from before the synch point
2025-07-02 06:41:16.187         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.187
2025-07-02 06:41:16.187         # do intraline marking on the synch pair
2025-07-02 06:41:16.187         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.187         if eqi is None:
2025-07-02 06:41:16.187             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.187             atags = btags = ""
2025-07-02 06:41:16.188             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.188             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.188                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.188                 if tag == 'replace':
2025-07-02 06:41:16.188                     atags += '^' * la
2025-07-02 06:41:16.188                     btags += '^' * lb
2025-07-02 06:41:16.188                 elif tag == 'delete':
2025-07-02 06:41:16.188                     atags += '-' * la
2025-07-02 06:41:16.188                 elif tag == 'insert':
2025-07-02 06:41:16.188                     btags += '+' * lb
2025-07-02 06:41:16.188                 elif tag == 'equal':
2025-07-02 06:41:16.188                     atags += ' ' * la
2025-07-02 06:41:16.188                     btags += ' ' * lb
2025-07-02 06:41:16.188                 else:
2025-07-02 06:41:16.188                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.188             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.188         else:
2025-07-02 06:41:16.188             # the synch pair is identical
2025-07-02 06:41:16.188             yield '  ' + aelt
2025-07-02 06:41:16.189
2025-07-02 06:41:16.189         # pump out diffs from after the synch point
2025-07-02 06:41:16.189 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.189
2025-07-02 06:41:16.189 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.189 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.189
2025-07-02 06:41:16.189 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.189 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.189 alo = 14, ahi = 1101
2025-07-02 06:41:16.189 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.189 blo = 14, bhi = 1101
2025-07-02 06:41:16.189
2025-07-02 06:41:16.189     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.189         g = []
2025-07-02 06:41:16.189         if alo < ahi:
2025-07-02 06:41:16.189             if blo < bhi:
2025-07-02 06:41:16.189                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.190             else:
2025-07-02 06:41:16.190                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.190         elif blo < bhi:
2025-07-02 06:41:16.190             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.190
2025-07-02 06:41:16.190 >       yield from g
2025-07-02 06:41:16.190
2025-07-02 06:41:16.190 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.190 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.190
2025-07-02 06:41:16.190 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.190 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.190 alo = 14, ahi = 1101
2025-07-02 06:41:16.190 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.190 blo = 14, bhi = 1101
2025-07-02 06:41:16.190
2025-07-02 06:41:16.190     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.190         r"""
2025-07-02 06:41:16.190         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.190         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.191         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.191         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.191
2025-07-02 06:41:16.191         Example:
2025-07-02 06:41:16.191
2025-07-02 06:41:16.191         >>> d = Differ()
2025-07-02 06:41:16.191         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.191         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.191         >>> print(''.join(results), end="")
2025-07-02 06:41:16.191         - abcDefghiJkl
2025-07-02 06:41:16.191         + abcdefGhijkl
2025-07-02 06:41:16.191         """
2025-07-02 06:41:16.191
2025-07-02 06:41:16.191         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.191         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.191         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.191         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.191         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.192
2025-07-02 06:41:16.192         # search for the pair that matches best without being identical
2025-07-02 06:41:16.192         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.192         # on junk -- unless we have to)
2025-07-02 06:41:16.192         for j in range(blo, bhi):
2025-07-02 06:41:16.192             bj = b[j]
2025-07-02 06:41:16.192             cruncher.set_seq2(bj)
2025-07-02 06:41:16.192             for i in range(alo, ahi):
2025-07-02 06:41:16.192                 ai = a[i]
2025-07-02 06:41:16.192                 if ai == bj:
2025-07-02 06:41:16.192                     if eqi is None:
2025-07-02 06:41:16.192                         eqi, eqj = i, j
2025-07-02 06:41:16.192                     continue
2025-07-02 06:41:16.192                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.192                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.192                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.192                 # compares by a factor of 3.
2025-07-02 06:41:16.192                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.193                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.193                 # of the computation is cached by cruncher
2025-07-02 06:41:16.193                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.193                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.193                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.193                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.193         if best_ratio < cutoff:
2025-07-02 06:41:16.193             # no non-identical "pretty close" pair
2025-07-02 06:41:16.193             if eqi is None:
2025-07-02 06:41:16.193                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.193                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.193                 return
2025-07-02 06:41:16.193             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.193             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.193         else:
2025-07-02 06:41:16.193             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.193             eqi = None
2025-07-02 06:41:16.193
2025-07-02 06:41:16.193         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.193         # identical
2025-07-02 06:41:16.194
2025-07-02 06:41:16.194         # pump out diffs from before the synch point
2025-07-02 06:41:16.194         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.194
2025-07-02 06:41:16.194         # do intraline marking on the synch pair
2025-07-02 06:41:16.194         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.194         if eqi is None:
2025-07-02 06:41:16.194             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.194             atags = btags = ""
2025-07-02 06:41:16.194             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.194             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.194                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.194                 if tag == 'replace':
2025-07-02 06:41:16.194                     atags += '^' * la
2025-07-02 06:41:16.194                     btags += '^' * lb
2025-07-02 06:41:16.194                 elif tag == 'delete':
2025-07-02 06:41:16.194                     atags += '-' * la
2025-07-02 06:41:16.194                 elif tag == 'insert':
2025-07-02 06:41:16.194                     btags += '+' * lb
2025-07-02 06:41:16.194                 elif tag == 'equal':
2025-07-02 06:41:16.195                     atags += ' ' * la
2025-07-02 06:41:16.195                     btags += ' ' * lb
2025-07-02 06:41:16.195                 else:
2025-07-02 06:41:16.195                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.195             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.195         else:
2025-07-02 06:41:16.195             # the synch pair is identical
2025-07-02 06:41:16.195             yield '  ' + aelt
2025-07-02 06:41:16.195
2025-07-02 06:41:16.195         # pump out diffs from after the synch point
2025-07-02 06:41:16.195 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.195
2025-07-02 06:41:16.195 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.195 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.195
2025-07-02 06:41:16.195 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.195 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.195 alo = 15, ahi = 1101
2025-07-02 06:41:16.195 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.195 blo = 15, bhi = 1101
2025-07-02 06:41:16.196
2025-07-02 06:41:16.196     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.196         g = []
2025-07-02 06:41:16.196         if alo < ahi:
2025-07-02 06:41:16.196             if blo < bhi:
2025-07-02 06:41:16.196                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.196             else:
2025-07-02 06:41:16.196                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.196         elif blo < bhi:
2025-07-02 06:41:16.196             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.196
2025-07-02 06:41:16.196 >       yield from g
2025-07-02 06:41:16.196
2025-07-02 06:41:16.196 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.196 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.196
2025-07-02 06:41:16.196 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.196 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.197 alo = 15, ahi = 1101
2025-07-02 06:41:16.197 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.197 blo = 15, bhi = 1101
2025-07-02 06:41:16.197
2025-07-02 06:41:16.197     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.197         r"""
2025-07-02 06:41:16.197         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.197         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.197         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.197         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.197
2025-07-02 06:41:16.197         Example:
2025-07-02 06:41:16.197
2025-07-02 06:41:16.197         >>> d = Differ()
2025-07-02 06:41:16.197         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.197         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.197         >>> print(''.join(results), end="")
2025-07-02 06:41:16.197         - abcDefghiJkl
2025-07-02 06:41:16.197         + abcdefGhijkl
2025-07-02 06:41:16.198         """
2025-07-02 06:41:16.198
2025-07-02 06:41:16.198         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.198         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.198         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.198         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.198         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.198
2025-07-02 06:41:16.198         # search for the pair that matches best without being identical
2025-07-02 06:41:16.198         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.198         # on junk -- unless we have to)
2025-07-02 06:41:16.198         for j in range(blo, bhi):
2025-07-02 06:41:16.198             bj = b[j]
2025-07-02 06:41:16.198             cruncher.set_seq2(bj)
2025-07-02 06:41:16.198             for i in range(alo, ahi):
2025-07-02 06:41:16.198                 ai = a[i]
2025-07-02 06:41:16.198                 if ai == bj:
2025-07-02 06:41:16.198                     if eqi is None:
2025-07-02 06:41:16.198                         eqi, eqj = i, j
2025-07-02 06:41:16.199                     continue
2025-07-02 06:41:16.199                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.199                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.199                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.199                 # compares by a factor of 3.
2025-07-02 06:41:16.199                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.199                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.199                 # of the computation is cached by cruncher
2025-07-02 06:41:16.199                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.199                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.199                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.199                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.199         if best_ratio < cutoff:
2025-07-02 06:41:16.199             # no non-identical "pretty close" pair
2025-07-02 06:41:16.199             if eqi is None:
2025-07-02 06:41:16.199                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.199                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.199                 return
2025-07-02 06:41:16.199             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.199             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.200         else:
2025-07-02 06:41:16.200             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.200             eqi = None
2025-07-02 06:41:16.200
2025-07-02 06:41:16.200         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.200         # identical
2025-07-02 06:41:16.200
2025-07-02 06:41:16.200         # pump out diffs from before the synch point
2025-07-02 06:41:16.200         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.200
2025-07-02 06:41:16.200         # do intraline marking on the synch pair
2025-07-02 06:41:16.200         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.200         if eqi is None:
2025-07-02 06:41:16.200             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.200             atags = btags = ""
2025-07-02 06:41:16.200             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.200             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.200                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.200                 if tag == 'replace':
2025-07-02 06:41:16.200                     atags += '^' * la
2025-07-02 06:41:16.200                     btags += '^' * lb
2025-07-02 06:41:16.201                 elif tag == 'delete':
2025-07-02 06:41:16.201                     atags += '-' * la
2025-07-02 06:41:16.201                 elif tag == 'insert':
2025-07-02 06:41:16.201                     btags += '+' * lb
2025-07-02 06:41:16.201                 elif tag == 'equal':
2025-07-02 06:41:16.201                     atags += ' ' * la
2025-07-02 06:41:16.201                     btags += ' ' * lb
2025-07-02 06:41:16.201                 else:
2025-07-02 06:41:16.201                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.201             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.201         else:
2025-07-02 06:41:16.201             # the synch pair is identical
2025-07-02 06:41:16.201             yield '  ' + aelt
2025-07-02 06:41:16.201
2025-07-02 06:41:16.201         # pump out diffs from after the synch point
2025-07-02 06:41:16.201 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.201
2025-07-02 06:41:16.201 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.201 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.201
2025-07-02 06:41:16.201 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.202 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.202 alo = 16, ahi = 1101
2025-07-02 06:41:16.202 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.202 blo = 16, bhi = 1101
2025-07-02 06:41:16.202
2025-07-02 06:41:16.202     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.202         g = []
2025-07-02 06:41:16.202         if alo < ahi:
2025-07-02 06:41:16.202             if blo < bhi:
2025-07-02 06:41:16.202                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.202             else:
2025-07-02 06:41:16.202                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.202         elif blo < bhi:
2025-07-02 06:41:16.202             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.202
2025-07-02 06:41:16.202 >       yield from g
2025-07-02 06:41:16.202
2025-07-02 06:41:16.202 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.202 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.202
2025-07-02 06:41:16.203 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.203 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.203 alo = 16, ahi = 1101
2025-07-02 06:41:16.203 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.203 blo = 16, bhi = 1101
2025-07-02 06:41:16.203
2025-07-02 06:41:16.203     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.203         r"""
2025-07-02 06:41:16.203         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.203         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.203         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.203         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.203
2025-07-02 06:41:16.203         Example:
2025-07-02 06:41:16.203
2025-07-02 06:41:16.203         >>> d = Differ()
2025-07-02 06:41:16.203         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.203         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.203         >>> print(''.join(results), end="")
2025-07-02 06:41:16.203         - abcDefghiJkl
2025-07-02 06:41:16.204         + abcdefGhijkl
2025-07-02 06:41:16.204         """
2025-07-02 06:41:16.204
2025-07-02 06:41:16.204         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.204         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.204         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.204         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.204         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.204
2025-07-02 06:41:16.204         # search for the pair that matches best without being identical
2025-07-02 06:41:16.204         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.204         # on junk -- unless we have to)
2025-07-02 06:41:16.204         for j in range(blo, bhi):
2025-07-02 06:41:16.204             bj = b[j]
2025-07-02 06:41:16.204             cruncher.set_seq2(bj)
2025-07-02 06:41:16.204             for i in range(alo, ahi):
2025-07-02 06:41:16.204                 ai = a[i]
2025-07-02 06:41:16.204                 if ai == bj:
2025-07-02 06:41:16.204                     if eqi is None:
2025-07-02 06:41:16.205                         eqi, eqj = i, j
2025-07-02 06:41:16.205                     continue
2025-07-02 06:41:16.205                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.205                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.205                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.205                 # compares by a factor of 3.
2025-07-02 06:41:16.205                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.205                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.205                 # of the computation is cached by cruncher
2025-07-02 06:41:16.205                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.205                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.205                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.205                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.205         if best_ratio < cutoff:
2025-07-02 06:41:16.205             # no non-identical "pretty close" pair
2025-07-02 06:41:16.205             if eqi is None:
2025-07-02 06:41:16.205                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.205                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.206                 return
2025-07-02 06:41:16.206             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.206             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.206         else:
2025-07-02 06:41:16.206             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.206             eqi = None
2025-07-02 06:41:16.206
2025-07-02 06:41:16.206         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.206         # identical
2025-07-02 06:41:16.206
2025-07-02 06:41:16.206         # pump out diffs from before the synch point
2025-07-02 06:41:16.206         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.206
2025-07-02 06:41:16.206         # do intraline marking on the synch pair
2025-07-02 06:41:16.206         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.206         if eqi is None:
2025-07-02 06:41:16.206             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.206             atags = btags = ""
2025-07-02 06:41:16.206             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.206             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.207                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.207                 if tag == 'replace':
2025-07-02 06:41:16.207                     atags += '^' * la
2025-07-02 06:41:16.207                     btags += '^' * lb
2025-07-02 06:41:16.207                 elif tag == 'delete':
2025-07-02 06:41:16.207                     atags += '-' * la
2025-07-02 06:41:16.207                 elif tag == 'insert':
2025-07-02 06:41:16.207                     btags += '+' * lb
2025-07-02 06:41:16.207                 elif tag == 'equal':
2025-07-02 06:41:16.207                     atags += ' ' * la
2025-07-02 06:41:16.207                     btags += ' ' * lb
2025-07-02 06:41:16.207                 else:
2025-07-02 06:41:16.207                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.207             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.207         else:
2025-07-02 06:41:16.207             # the synch pair is identical
2025-07-02 06:41:16.207             yield '  ' + aelt
2025-07-02 06:41:16.207
2025-07-02 06:41:16.207         # pump out diffs from after the synch point
2025-07-02 06:41:16.207 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.207
2025-07-02 06:41:16.208 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.208 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.208
2025-07-02 06:41:16.208 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.208 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.208 alo = 17, ahi = 1101
2025-07-02 06:41:16.208 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.208 blo = 17, bhi = 1101
2025-07-02 06:41:16.208
2025-07-02 06:41:16.208     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.208         g = []
2025-07-02 06:41:16.208         if alo < ahi:
2025-07-02 06:41:16.208             if blo < bhi:
2025-07-02 06:41:16.208                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.208             else:
2025-07-02 06:41:16.208                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.208         elif blo < bhi:
2025-07-02 06:41:16.208             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.209
2025-07-02 06:41:16.209 >       yield from g
2025-07-02 06:41:16.209
2025-07-02 06:41:16.209 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.209 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.209
2025-07-02 06:41:16.209 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.209 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.209 alo = 17, ahi = 1101
2025-07-02 06:41:16.209 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.209 blo = 17, bhi = 1101
2025-07-02 06:41:16.209
2025-07-02 06:41:16.209     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.209         r"""
2025-07-02 06:41:16.209         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.209         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.209         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.209         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.209
2025-07-02 06:41:16.210         Example:
2025-07-02 06:41:16.210
2025-07-02 06:41:16.210         >>> d = Differ()
2025-07-02 06:41:16.210         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.210         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.210         >>> print(''.join(results), end="")
2025-07-02 06:41:16.210         - abcDefghiJkl
2025-07-02 06:41:16.210         + abcdefGhijkl
2025-07-02 06:41:16.210         """
2025-07-02 06:41:16.210
2025-07-02 06:41:16.210         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.210         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.210         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.210         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.210         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.210
2025-07-02 06:41:16.210         # search for the pair that matches best without being identical
2025-07-02 06:41:16.210         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.210         # on junk -- unless we have to)
2025-07-02 06:41:16.211         for j in range(blo, bhi):
2025-07-02 06:41:16.211             bj = b[j]
2025-07-02 06:41:16.211             cruncher.set_seq2(bj)
2025-07-02 06:41:16.211             for i in range(alo, ahi):
2025-07-02 06:41:16.211                 ai = a[i]
2025-07-02 06:41:16.211                 if ai == bj:
2025-07-02 06:41:16.211                     if eqi is None:
2025-07-02 06:41:16.211                         eqi, eqj = i, j
2025-07-02 06:41:16.211                     continue
2025-07-02 06:41:16.211                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.211                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.211                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.211                 # compares by a factor of 3.
2025-07-02 06:41:16.211                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.211                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.211                 # of the computation is cached by cruncher
2025-07-02 06:41:16.211                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.211                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.211                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.211                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.212         if best_ratio < cutoff:
2025-07-02 06:41:16.212             # no non-identical "pretty close" pair
2025-07-02 06:41:16.212             if eqi is None:
2025-07-02 06:41:16.212                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.212                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.212                 return
2025-07-02 06:41:16.212             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.212             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.212         else:
2025-07-02 06:41:16.212             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.212             eqi = None
2025-07-02 06:41:16.212
2025-07-02 06:41:16.212         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.212         # identical
2025-07-02 06:41:16.212
2025-07-02 06:41:16.212         # pump out diffs from before the synch point
2025-07-02 06:41:16.212         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.212
2025-07-02 06:41:16.212         # do intraline marking on the synch pair
2025-07-02 06:41:16.212         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.213         if eqi is None:
2025-07-02 06:41:16.213             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.213             atags = btags = ""
2025-07-02 06:41:16.213             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.213             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.213                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.213                 if tag == 'replace':
2025-07-02 06:41:16.213                     atags += '^' * la
2025-07-02 06:41:16.213                     btags += '^' * lb
2025-07-02 06:41:16.213                 elif tag == 'delete':
2025-07-02 06:41:16.213                     atags += '-' * la
2025-07-02 06:41:16.213                 elif tag == 'insert':
2025-07-02 06:41:16.213                     btags += '+' * lb
2025-07-02 06:41:16.213                 elif tag == 'equal':
2025-07-02 06:41:16.213                     atags += ' ' * la
2025-07-02 06:41:16.213                     btags += ' ' * lb
2025-07-02 06:41:16.213                 else:
2025-07-02 06:41:16.213                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.213             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.214         else:
2025-07-02 06:41:16.214             # the synch pair is identical
2025-07-02 06:41:16.214             yield '  ' + aelt
2025-07-02 06:41:16.214
2025-07-02 06:41:16.214         # pump out diffs from after the synch point
2025-07-02 06:41:16.214 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.214
2025-07-02 06:41:16.214 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.214 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.214
2025-07-02 06:41:16.214 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.214 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.214 alo = 18, ahi = 1101
2025-07-02 06:41:16.214 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.214 blo = 18, bhi = 1101
2025-07-02 06:41:16.214
2025-07-02 06:41:16.214     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.214         g = []
2025-07-02 06:41:16.215         if alo < ahi:
2025-07-02 06:41:16.215             if blo < bhi:
2025-07-02 06:41:16.215                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.215             else:
2025-07-02 06:41:16.215                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.215         elif blo < bhi:
2025-07-02 06:41:16.215             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.215
2025-07-02 06:41:16.215 >       yield from g
2025-07-02 06:41:16.215
2025-07-02 06:41:16.215 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.215 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.215
2025-07-02 06:41:16.215 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.215 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.215 alo = 18, ahi = 1101
2025-07-02 06:41:16.215 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.215 blo = 18, bhi = 1101
2025-07-02 06:41:16.215
2025-07-02 06:41:16.215     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.216         r"""
2025-07-02 06:41:16.216         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.216         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.216         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.216         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.216
2025-07-02 06:41:16.216         Example:
2025-07-02 06:41:16.216
2025-07-02 06:41:16.216         >>> d = Differ()
2025-07-02 06:41:16.216         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.216         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.216         >>> print(''.join(results), end="")
2025-07-02 06:41:16.216         - abcDefghiJkl
2025-07-02 06:41:16.216         + abcdefGhijkl
2025-07-02 06:41:16.216         """
2025-07-02 06:41:16.216
2025-07-02 06:41:16.216         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.216         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.217         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.217         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.217         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.217
2025-07-02 06:41:16.217         # search for the pair that matches best without being identical
2025-07-02 06:41:16.217         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.217         # on junk -- unless we have to)
2025-07-02 06:41:16.217         for j in range(blo, bhi):
2025-07-02 06:41:16.217             bj = b[j]
2025-07-02 06:41:16.217             cruncher.set_seq2(bj)
2025-07-02 06:41:16.217             for i in range(alo, ahi):
2025-07-02 06:41:16.217                 ai = a[i]
2025-07-02 06:41:16.217                 if ai == bj:
2025-07-02 06:41:16.217                     if eqi is None:
2025-07-02 06:41:16.217                         eqi, eqj = i, j
2025-07-02 06:41:16.217                     continue
2025-07-02 06:41:16.217                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.217                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.217                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.217                 # compares by a factor of 3.
2025-07-02 06:41:16.217                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.218                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.218                 # of the computation is cached by cruncher
2025-07-02 06:41:16.218                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.218                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.218                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.218                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.218         if best_ratio < cutoff:
2025-07-02 06:41:16.218             # no non-identical "pretty close" pair
2025-07-02 06:41:16.218             if eqi is None:
2025-07-02 06:41:16.218                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.218                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.218                 return
2025-07-02 06:41:16.218             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.218             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.218         else:
2025-07-02 06:41:16.218             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.218             eqi = None
2025-07-02 06:41:16.218
2025-07-02 06:41:16.218         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.218         # identical
2025-07-02 06:41:16.219
2025-07-02 06:41:16.219         # pump out diffs from before the synch point
2025-07-02 06:41:16.219         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.219
2025-07-02 06:41:16.219         # do intraline marking on the synch pair
2025-07-02 06:41:16.219         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.219         if eqi is None:
2025-07-02 06:41:16.219             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.219             atags = btags = ""
2025-07-02 06:41:16.219             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.219             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.219                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.219                 if tag == 'replace':
2025-07-02 06:41:16.219                     atags += '^' * la
2025-07-02 06:41:16.219                     btags += '^' * lb
2025-07-02 06:41:16.219                 elif tag == 'delete':
2025-07-02 06:41:16.219                     atags += '-' * la
2025-07-02 06:41:16.219                 elif tag == 'insert':
2025-07-02 06:41:16.219                     btags += '+' * lb
2025-07-02 06:41:16.219                 elif tag == 'equal':
2025-07-02 06:41:16.219                     atags += ' ' * la
2025-07-02 06:41:16.220                     btags += ' ' * lb
2025-07-02 06:41:16.220                 else:
2025-07-02 06:41:16.220                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.220             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.220         else:
2025-07-02 06:41:16.220             # the synch pair is identical
2025-07-02 06:41:16.220             yield '  ' + aelt
2025-07-02 06:41:16.220
2025-07-02 06:41:16.220         # pump out diffs from after the synch point
2025-07-02 06:41:16.220 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.220
2025-07-02 06:41:16.220 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.220 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.220
2025-07-02 06:41:16.220 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.220 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.220 alo = 19, ahi = 1101
2025-07-02 06:41:16.220 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.220 blo = 19, bhi = 1101
2025-07-02 06:41:16.220
2025-07-02 06:41:16.221     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.221         g = []
2025-07-02 06:41:16.221         if alo < ahi:
2025-07-02 06:41:16.221             if blo < bhi:
2025-07-02 06:41:16.221                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.221             else:
2025-07-02 06:41:16.221                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.221         elif blo < bhi:
2025-07-02 06:41:16.221             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.221
2025-07-02 06:41:16.221 >       yield from g
2025-07-02 06:41:16.221
2025-07-02 06:41:16.221 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.221 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.221
2025-07-02 06:41:16.221 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.221 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.221 alo = 19, ahi = 1101
2025-07-02 06:41:16.221 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.221 blo = 19, bhi = 1101
2025-07-02 06:41:16.222
2025-07-02 06:41:16.222     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.222         r"""
2025-07-02 06:41:16.222         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.222         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.222         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.222         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.222
2025-07-02 06:41:16.222         Example:
2025-07-02 06:41:16.222
2025-07-02 06:41:16.222         >>> d = Differ()
2025-07-02 06:41:16.222         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.222         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.222         >>> print(''.join(results), end="")
2025-07-02 06:41:16.222         - abcDefghiJkl
2025-07-02 06:41:16.222         + abcdefGhijkl
2025-07-02 06:41:16.222         """
2025-07-02 06:41:16.223
2025-07-02 06:41:16.223         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.223         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.223         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.223         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.223         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.223
2025-07-02 06:41:16.223         # search for the pair that matches best without being identical
2025-07-02 06:41:16.223         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.223         # on junk -- unless we have to)
2025-07-02 06:41:16.223         for j in range(blo, bhi):
2025-07-02 06:41:16.223             bj = b[j]
2025-07-02 06:41:16.223             cruncher.set_seq2(bj)
2025-07-02 06:41:16.223             for i in range(alo, ahi):
2025-07-02 06:41:16.223                 ai = a[i]
2025-07-02 06:41:16.223                 if ai == bj:
2025-07-02 06:41:16.223                     if eqi is None:
2025-07-02 06:41:16.223                         eqi, eqj = i, j
2025-07-02 06:41:16.223                     continue
2025-07-02 06:41:16.224                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.224                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.224                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.224                 # compares by a factor of 3.
2025-07-02 06:41:16.224                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.224                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.224                 # of the computation is cached by cruncher
2025-07-02 06:41:16.224                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.224                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.224                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.224                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.224         if best_ratio < cutoff:
2025-07-02 06:41:16.224             # no non-identical "pretty close" pair
2025-07-02 06:41:16.224             if eqi is None:
2025-07-02 06:41:16.224                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.224                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.224                 return
2025-07-02 06:41:16.224             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.225             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.225         else:
2025-07-02 06:41:16.225             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.225             eqi = None
2025-07-02 06:41:16.225
2025-07-02 06:41:16.225         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.225         # identical
2025-07-02 06:41:16.225
2025-07-02 06:41:16.225         # pump out diffs from before the synch point
2025-07-02 06:41:16.225         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.225
2025-07-02 06:41:16.225         # do intraline marking on the synch pair
2025-07-02 06:41:16.225         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.225         if eqi is None:
2025-07-02 06:41:16.225             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.225             atags = btags = ""
2025-07-02 06:41:16.225             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.225             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.225                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.225                 if tag == 'replace':
2025-07-02 06:41:16.226                     atags += '^' * la
2025-07-02 06:41:16.226                     btags += '^' * lb
2025-07-02 06:41:16.226                 elif tag == 'delete':
2025-07-02 06:41:16.226                     atags += '-' * la
2025-07-02 06:41:16.226                 elif tag == 'insert':
2025-07-02 06:41:16.226                     btags += '+' * lb
2025-07-02 06:41:16.226                 elif tag == 'equal':
2025-07-02 06:41:16.226                     atags += ' ' * la
2025-07-02 06:41:16.226                     btags += ' ' * lb
2025-07-02 06:41:16.226                 else:
2025-07-02 06:41:16.226                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.226             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.226         else:
2025-07-02 06:41:16.226             # the synch pair is identical
2025-07-02 06:41:16.226             yield '  ' + aelt
2025-07-02 06:41:16.226
2025-07-02 06:41:16.226         # pump out diffs from after the synch point
2025-07-02 06:41:16.226 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.226
2025-07-02 06:41:16.226 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.227 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.227
2025-07-02 06:41:16.227 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.227 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.227 alo = 20, ahi = 1101
2025-07-02 06:41:16.227 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.227 blo = 20, bhi = 1101
2025-07-02 06:41:16.227
2025-07-02 06:41:16.227     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.227         g = []
2025-07-02 06:41:16.227         if alo < ahi:
2025-07-02 06:41:16.227             if blo < bhi:
2025-07-02 06:41:16.227                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.227             else:
2025-07-02 06:41:16.227                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.227         elif blo < bhi:
2025-07-02 06:41:16.227             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.227
2025-07-02 06:41:16.227 >       yield from g
2025-07-02 06:41:16.227
2025-07-02 06:41:16.228 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.228 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.228
2025-07-02 06:41:16.228 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.228 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.228 alo = 20, ahi = 1101
2025-07-02 06:41:16.228 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.228 blo = 20, bhi = 1101
2025-07-02 06:41:16.228
2025-07-02 06:41:16.228     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.228         r"""
2025-07-02 06:41:16.228         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.228         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.228         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.228         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.228
2025-07-02 06:41:16.228         Example:
2025-07-02 06:41:16.228
2025-07-02 06:41:16.228         >>> d = Differ()
2025-07-02 06:41:16.228         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.229         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.229         >>> print(''.join(results), end="")
2025-07-02 06:41:16.229         - abcDefghiJkl
2025-07-02 06:41:16.229         + abcdefGhijkl
2025-07-02 06:41:16.229         """
2025-07-02 06:41:16.229
2025-07-02 06:41:16.229         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.229         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.229         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.229         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.229         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.229
2025-07-02 06:41:16.229         # search for the pair that matches best without being identical
2025-07-02 06:41:16.229         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.229         # on junk -- unless we have to)
2025-07-02 06:41:16.229         for j in range(blo, bhi):
2025-07-02 06:41:16.229             bj = b[j]
2025-07-02 06:41:16.229             cruncher.set_seq2(bj)
2025-07-02 06:41:16.230             for i in range(alo, ahi):
2025-07-02 06:41:16.230                 ai = a[i]
2025-07-02 06:41:16.230                 if ai == bj:
2025-07-02 06:41:16.230                     if eqi is None:
2025-07-02 06:41:16.230                         eqi, eqj = i, j
2025-07-02 06:41:16.230                     continue
2025-07-02 06:41:16.230                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.230                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.230                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.230                 # compares by a factor of 3.
2025-07-02 06:41:16.230                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.230                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.230                 # of the computation is cached by cruncher
2025-07-02 06:41:16.230                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.230                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.230                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.230                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.230         if best_ratio < cutoff:
2025-07-02 06:41:16.230             # no non-identical "pretty close" pair
2025-07-02 06:41:16.230             if eqi is None:
2025-07-02 06:41:16.231                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.231                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.231                 return
2025-07-02 06:41:16.231             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.231             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.231         else:
2025-07-02 06:41:16.231             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.231             eqi = None
2025-07-02 06:41:16.231
2025-07-02 06:41:16.231         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.231         # identical
2025-07-02 06:41:16.231
2025-07-02 06:41:16.231         # pump out diffs from before the synch point
2025-07-02 06:41:16.231         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.231
2025-07-02 06:41:16.231         # do intraline marking on the synch pair
2025-07-02 06:41:16.231         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.231         if eqi is None:
2025-07-02 06:41:16.232             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.232             atags = btags = ""
2025-07-02 06:41:16.232             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.232             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.232                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.232                 if tag == 'replace':
2025-07-02 06:41:16.232                     atags += '^' * la
2025-07-02 06:41:16.232                     btags += '^' * lb
2025-07-02 06:41:16.232                 elif tag == 'delete':
2025-07-02 06:41:16.232                     atags += '-' * la
2025-07-02 06:41:16.232                 elif tag == 'insert':
2025-07-02 06:41:16.232                     btags += '+' * lb
2025-07-02 06:41:16.232                 elif tag == 'equal':
2025-07-02 06:41:16.232                     atags += ' ' * la
2025-07-02 06:41:16.232                     btags += ' ' * lb
2025-07-02 06:41:16.232                 else:
2025-07-02 06:41:16.232                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.232             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.232         else:
2025-07-02 06:41:16.233             # the synch pair is identical
2025-07-02 06:41:16.233             yield '  ' + aelt
2025-07-02 06:41:16.233
2025-07-02 06:41:16.233         # pump out diffs from after the synch point
2025-07-02 06:41:16.233 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.233
2025-07-02 06:41:16.233 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.233 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.233
2025-07-02 06:41:16.233 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.233 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.233 alo = 21, ahi = 1101
2025-07-02 06:41:16.233 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.233 blo = 21, bhi = 1101
2025-07-02 06:41:16.233
2025-07-02 06:41:16.233     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.233         g = []
2025-07-02 06:41:16.233         if alo < ahi:
2025-07-02 06:41:16.233             if blo < bhi:
2025-07-02 06:41:16.233                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.234             else:
2025-07-02 06:41:16.234                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.234         elif blo < bhi:
2025-07-02 06:41:16.234             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.234
2025-07-02 06:41:16.234 >       yield from g
2025-07-02 06:41:16.234
2025-07-02 06:41:16.234 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.234 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.234
2025-07-02 06:41:16.234 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.234 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.234 alo = 21, ahi = 1101
2025-07-02 06:41:16.234 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.234 blo = 21, bhi = 1101
2025-07-02 06:41:16.234
2025-07-02 06:41:16.234     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.234         r"""
2025-07-02 06:41:16.234         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.235         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.235         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.235         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.235
2025-07-02 06:41:16.235         Example:
2025-07-02 06:41:16.235
2025-07-02 06:41:16.235         >>> d = Differ()
2025-07-02 06:41:16.235         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.235         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.235         >>> print(''.join(results), end="")
2025-07-02 06:41:16.235         - abcDefghiJkl
2025-07-02 06:41:16.235         + abcdefGhijkl
2025-07-02 06:41:16.235         """
2025-07-02 06:41:16.235
2025-07-02 06:41:16.235         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.235         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.235         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.235         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.236         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.236
2025-07-02 06:41:16.236         # search for the pair that matches best without being identical
2025-07-02 06:41:16.236         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.236         # on junk -- unless we have to)
2025-07-02 06:41:16.236         for j in range(blo, bhi):
2025-07-02 06:41:16.236             bj = b[j]
2025-07-02 06:41:16.236             cruncher.set_seq2(bj)
2025-07-02 06:41:16.236             for i in range(alo, ahi):
2025-07-02 06:41:16.236                 ai = a[i]
2025-07-02 06:41:16.236                 if ai == bj:
2025-07-02 06:41:16.236                     if eqi is None:
2025-07-02 06:41:16.236                         eqi, eqj = i, j
2025-07-02 06:41:16.236                     continue
2025-07-02 06:41:16.236                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.236                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.236                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.237                 # compares by a factor of 3.
2025-07-02 06:41:16.237                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.237                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.237                 # of the computation is cached by cruncher
2025-07-02 06:41:16.237                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.237                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.237                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.237                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.237         if best_ratio < cutoff:
2025-07-02 06:41:16.237             # no non-identical "pretty close" pair
2025-07-02 06:41:16.237             if eqi is None:
2025-07-02 06:41:16.237                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.237                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.237                 return
2025-07-02 06:41:16.237             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.237             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.237         else:
2025-07-02 06:41:16.237             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.237             eqi = None
2025-07-02 06:41:16.238
2025-07-02 06:41:16.238         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.238         # identical
2025-07-02 06:41:16.238
2025-07-02 06:41:16.238         # pump out diffs from before the synch point
2025-07-02 06:41:16.238         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.238
2025-07-02 06:41:16.238         # do intraline marking on the synch pair
2025-07-02 06:41:16.238         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.238         if eqi is None:
2025-07-02 06:41:16.238             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.238             atags = btags = ""
2025-07-02 06:41:16.238             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.238             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.238                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.238                 if tag == 'replace':
2025-07-02 06:41:16.238                     atags += '^' * la
2025-07-02 06:41:16.238                     btags += '^' * lb
2025-07-02 06:41:16.238                 elif tag == 'delete':
2025-07-02 06:41:16.238                     atags += '-' * la
2025-07-02 06:41:16.238                 elif tag == 'insert':
2025-07-02 06:41:16.239                     btags += '+' * lb
2025-07-02 06:41:16.239                 elif tag == 'equal':
2025-07-02 06:41:16.239                     atags += ' ' * la
2025-07-02 06:41:16.239                     btags += ' ' * lb
2025-07-02 06:41:16.239                 else:
2025-07-02 06:41:16.239                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.239             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.239         else:
2025-07-02 06:41:16.239             # the synch pair is identical
2025-07-02 06:41:16.239             yield '  ' + aelt
2025-07-02 06:41:16.239
2025-07-02 06:41:16.239         # pump out diffs from after the synch point
2025-07-02 06:41:16.239 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.239
2025-07-02 06:41:16.239 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.239 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.239
2025-07-02 06:41:16.239 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.239 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.239 alo = 22, ahi = 1101
2025-07-02 06:41:16.240 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.240 blo = 22, bhi = 1101
2025-07-02 06:41:16.240
2025-07-02 06:41:16.240     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.240         g = []
2025-07-02 06:41:16.240         if alo < ahi:
2025-07-02 06:41:16.240             if blo < bhi:
2025-07-02 06:41:16.240                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.240             else:
2025-07-02 06:41:16.240                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.240         elif blo < bhi:
2025-07-02 06:41:16.240             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.240
2025-07-02 06:41:16.240 >       yield from g
2025-07-02 06:41:16.240
2025-07-02 06:41:16.240 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.240 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.241
2025-07-02 06:41:16.241 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.241 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.241 alo = 22, ahi = 1101
2025-07-02 06:41:16.241 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.241 blo = 22, bhi = 1101
2025-07-02 06:41:16.241
2025-07-02 06:41:16.241     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.241         r"""
2025-07-02 06:41:16.241         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.241         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.241         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.241         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.241
2025-07-02 06:41:16.241         Example:
2025-07-02 06:41:16.241
2025-07-02 06:41:16.241         >>> d = Differ()
2025-07-02 06:41:16.241         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.241         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.242         >>> print(''.join(results), end="")
2025-07-02 06:41:16.242         - abcDefghiJkl
2025-07-02 06:41:16.242         + abcdefGhijkl
2025-07-02 06:41:16.242         """
2025-07-02 06:41:16.242
2025-07-02 06:41:16.242         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.242         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.242         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.242         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.242         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.242
2025-07-02 06:41:16.242         # search for the pair that matches best without being identical
2025-07-02 06:41:16.242         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.242         # on junk -- unless we have to)
2025-07-02 06:41:16.242         for j in range(blo, bhi):
2025-07-02 06:41:16.242             bj = b[j]
2025-07-02 06:41:16.242             cruncher.set_seq2(bj)
2025-07-02 06:41:16.242             for i in range(alo, ahi):
2025-07-02 06:41:16.243                 ai = a[i]
2025-07-02 06:41:16.243                 if ai == bj:
2025-07-02 06:41:16.243                     if eqi is None:
2025-07-02 06:41:16.243                         eqi, eqj = i, j
2025-07-02 06:41:16.243                     continue
2025-07-02 06:41:16.243                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.243                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.243                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.243                 # compares by a factor of 3.
2025-07-02 06:41:16.243                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.243                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.243                 # of the computation is cached by cruncher
2025-07-02 06:41:16.243                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.243                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.243                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.243                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.243         if best_ratio < cutoff:
2025-07-02 06:41:16.243             # no non-identical "pretty close" pair
2025-07-02 06:41:16.243             if eqi is None:
2025-07-02 06:41:16.244                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.244                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.244                 return
2025-07-02 06:41:16.244             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.244             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.244         else:
2025-07-02 06:41:16.244             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.244             eqi = None
2025-07-02 06:41:16.244
2025-07-02 06:41:16.244         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.244         # identical
2025-07-02 06:41:16.244
2025-07-02 06:41:16.244         # pump out diffs from before the synch point
2025-07-02 06:41:16.244         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.244
2025-07-02 06:41:16.244         # do intraline marking on the synch pair
2025-07-02 06:41:16.244         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.244         if eqi is None:
2025-07-02 06:41:16.244             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.244             atags = btags = ""
2025-07-02 06:41:16.245             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.245             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.245                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.245                 if tag == 'replace':
2025-07-02 06:41:16.245                     atags += '^' * la
2025-07-02 06:41:16.245                     btags += '^' * lb
2025-07-02 06:41:16.245                 elif tag == 'delete':
2025-07-02 06:41:16.245                     atags += '-' * la
2025-07-02 06:41:16.245                 elif tag == 'insert':
2025-07-02 06:41:16.245                     btags += '+' * lb
2025-07-02 06:41:16.245                 elif tag == 'equal':
2025-07-02 06:41:16.245                     atags += ' ' * la
2025-07-02 06:41:16.245                     btags += ' ' * lb
2025-07-02 06:41:16.245                 else:
2025-07-02 06:41:16.245                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.245             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.245         else:
2025-07-02 06:41:16.245             # the synch pair is identical
2025-07-02 06:41:16.245             yield '  ' + aelt
2025-07-02 06:41:16.245
2025-07-02 06:41:16.246         # pump out diffs from after the synch point
2025-07-02 06:41:16.246 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.246
2025-07-02 06:41:16.246 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.246 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.246
2025-07-02 06:41:16.246 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.246 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.246 alo = 23, ahi = 1101
2025-07-02 06:41:16.246 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.246 blo = 23, bhi = 1101
2025-07-02 06:41:16.246
2025-07-02 06:41:16.246     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.246         g = []
2025-07-02 06:41:16.246         if alo < ahi:
2025-07-02 06:41:16.246             if blo < bhi:
2025-07-02 06:41:16.246                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.246             else:
2025-07-02 06:41:16.246                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.246         elif blo < bhi:
2025-07-02 06:41:16.246             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247 >       yield from g
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.247 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.247 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.247 alo = 23, ahi = 1101
2025-07-02 06:41:16.247 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.247 blo = 23, bhi = 1101
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.247         r"""
2025-07-02 06:41:16.247         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.247         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.247         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.247         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.247
2025-07-02 06:41:16.247         Example:
2025-07-02 06:41:16.248
2025-07-02 06:41:16.248         >>> d = Differ()
2025-07-02 06:41:16.248         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.248         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.248         >>> print(''.join(results), end="")
2025-07-02 06:41:16.248         - abcDefghiJkl
2025-07-02 06:41:16.248         + abcdefGhijkl
2025-07-02 06:41:16.248         """
2025-07-02 06:41:16.248
2025-07-02 06:41:16.248         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.248         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.248         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.248         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.248         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.248
2025-07-02 06:41:16.248         # search for the pair that matches best without being identical
2025-07-02 06:41:16.248         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.249         # on junk -- unless we have to)
2025-07-02 06:41:16.249         for j in range(blo, bhi):
2025-07-02 06:41:16.249             bj = b[j]
2025-07-02 06:41:16.249             cruncher.set_seq2(bj)
2025-07-02 06:41:16.249             for i in range(alo, ahi):
2025-07-02 06:41:16.249                 ai = a[i]
2025-07-02 06:41:16.249                 if ai == bj:
2025-07-02 06:41:16.249                     if eqi is None:
2025-07-02 06:41:16.249                         eqi, eqj = i, j
2025-07-02 06:41:16.249                     continue
2025-07-02 06:41:16.249                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.249                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.249                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.249                 # compares by a factor of 3.
2025-07-02 06:41:16.249                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.249                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.249                 # of the computation is cached by cruncher
2025-07-02 06:41:16.249                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.249                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.249                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.250                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.250         if best_ratio < cutoff:
2025-07-02 06:41:16.250             # no non-identical "pretty close" pair
2025-07-02 06:41:16.250             if eqi is None:
2025-07-02 06:41:16.250                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.250                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.250                 return
2025-07-02 06:41:16.250             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.250             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.250         else:
2025-07-02 06:41:16.250             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.250             eqi = None
2025-07-02 06:41:16.250
2025-07-02 06:41:16.250         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.250         # identical
2025-07-02 06:41:16.250
2025-07-02 06:41:16.250         # pump out diffs from before the synch point
2025-07-02 06:41:16.250         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.250
2025-07-02 06:41:16.251         # do intraline marking on the synch pair
2025-07-02 06:41:16.251         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.251         if eqi is None:
2025-07-02 06:41:16.251             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.251             atags = btags = ""
2025-07-02 06:41:16.251             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.251             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.251                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.251                 if tag == 'replace':
2025-07-02 06:41:16.251                     atags += '^' * la
2025-07-02 06:41:16.251                     btags += '^' * lb
2025-07-02 06:41:16.251                 elif tag == 'delete':
2025-07-02 06:41:16.251                     atags += '-' * la
2025-07-02 06:41:16.251                 elif tag == 'insert':
2025-07-02 06:41:16.251                     btags += '+' * lb
2025-07-02 06:41:16.251                 elif tag == 'equal':
2025-07-02 06:41:16.251                     atags += ' ' * la
2025-07-02 06:41:16.251                     btags += ' ' * lb
2025-07-02 06:41:16.251                 else:
2025-07-02 06:41:16.251                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.252             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.252         else:
2025-07-02 06:41:16.252             # the synch pair is identical
2025-07-02 06:41:16.252             yield '  ' + aelt
2025-07-02 06:41:16.252
2025-07-02 06:41:16.252         # pump out diffs from after the synch point
2025-07-02 06:41:16.252 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.252
2025-07-02 06:41:16.252 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.252 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.252
2025-07-02 06:41:16.252 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.252 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.252 alo = 26, ahi = 1101
2025-07-02 06:41:16.252 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.252 blo = 26, bhi = 1101
2025-07-02 06:41:16.252
2025-07-02 06:41:16.252     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.252         g = []
2025-07-02 06:41:16.252         if alo < ahi:
2025-07-02 06:41:16.253             if blo < bhi:
2025-07-02 06:41:16.253                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.253             else:
2025-07-02 06:41:16.253                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.253         elif blo < bhi:
2025-07-02 06:41:16.253             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.253
2025-07-02 06:41:16.253 >       yield from g
2025-07-02 06:41:16.253
2025-07-02 06:41:16.253 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.253 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.253
2025-07-02 06:41:16.253 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.253 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.253 alo = 26, ahi = 1101
2025-07-02 06:41:16.253 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.253 blo = 26, bhi = 1101
2025-07-02 06:41:16.253
2025-07-02 06:41:16.253     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.253         r"""
2025-07-02 06:41:16.254         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.254         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.254         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.254         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.254
2025-07-02 06:41:16.254         Example:
2025-07-02 06:41:16.254
2025-07-02 06:41:16.254         >>> d = Differ()
2025-07-02 06:41:16.254         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.254         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.254         >>> print(''.join(results), end="")
2025-07-02 06:41:16.254         - abcDefghiJkl
2025-07-02 06:41:16.254         + abcdefGhijkl
2025-07-02 06:41:16.254         """
2025-07-02 06:41:16.254
2025-07-02 06:41:16.254         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.254         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.254         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.255         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.255         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.255
2025-07-02 06:41:16.255         # search for the pair that matches best without being identical
2025-07-02 06:41:16.255         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.255         # on junk -- unless we have to)
2025-07-02 06:41:16.255         for j in range(blo, bhi):
2025-07-02 06:41:16.255             bj = b[j]
2025-07-02 06:41:16.255             cruncher.set_seq2(bj)
2025-07-02 06:41:16.255             for i in range(alo, ahi):
2025-07-02 06:41:16.255                 ai = a[i]
2025-07-02 06:41:16.255                 if ai == bj:
2025-07-02 06:41:16.255                     if eqi is None:
2025-07-02 06:41:16.255                         eqi, eqj = i, j
2025-07-02 06:41:16.255                     continue
2025-07-02 06:41:16.255                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.255                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.255                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.256                 # compares by a factor of 3.
2025-07-02 06:41:16.256                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.256                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.256                 # of the computation is cached by cruncher
2025-07-02 06:41:16.256                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.256                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.256                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.256                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.256         if best_ratio < cutoff:
2025-07-02 06:41:16.256             # no non-identical "pretty close" pair
2025-07-02 06:41:16.256             if eqi is None:
2025-07-02 06:41:16.256                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.256                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.256                 return
2025-07-02 06:41:16.256             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.256             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.256         else:
2025-07-02 06:41:16.256             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.256             eqi = None
2025-07-02 06:41:16.256
2025-07-02 06:41:16.257         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.257         # identical
2025-07-02 06:41:16.257
2025-07-02 06:41:16.257         # pump out diffs from before the synch point
2025-07-02 06:41:16.257         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.257
2025-07-02 06:41:16.257         # do intraline marking on the synch pair
2025-07-02 06:41:16.257         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.257         if eqi is None:
2025-07-02 06:41:16.257             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.257             atags = btags = ""
2025-07-02 06:41:16.257             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.257             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.257                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.257                 if tag == 'replace':
2025-07-02 06:41:16.257                     atags += '^' * la
2025-07-02 06:41:16.257                     btags += '^' * lb
2025-07-02 06:41:16.257                 elif tag == 'delete':
2025-07-02 06:41:16.258                     atags += '-' * la
2025-07-02 06:41:16.258                 elif tag == 'insert':
2025-07-02 06:41:16.258                     btags += '+' * lb
2025-07-02 06:41:16.258                 elif tag == 'equal':
2025-07-02 06:41:16.258                     atags += ' ' * la
2025-07-02 06:41:16.258                     btags += ' ' * lb
2025-07-02 06:41:16.258                 else:
2025-07-02 06:41:16.258                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.258             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.258         else:
2025-07-02 06:41:16.258             # the synch pair is identical
2025-07-02 06:41:16.258             yield '  ' + aelt
2025-07-02 06:41:16.258
2025-07-02 06:41:16.258         # pump out diffs from after the synch point
2025-07-02 06:41:16.258 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.258
2025-07-02 06:41:16.258 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.258 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.258
2025-07-02 06:41:16.258 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.259 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.259 alo = 27, ahi = 1101
2025-07-02 06:41:16.259 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.259 blo = 27, bhi = 1101
2025-07-02 06:41:16.259
2025-07-02 06:41:16.259     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.259         g = []
2025-07-02 06:41:16.259         if alo < ahi:
2025-07-02 06:41:16.259             if blo < bhi:
2025-07-02 06:41:16.259                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.259             else:
2025-07-02 06:41:16.259                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.259         elif blo < bhi:
2025-07-02 06:41:16.259             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.259
2025-07-02 06:41:16.259 >       yield from g
2025-07-02 06:41:16.259
2025-07-02 06:41:16.259 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.259 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.259
2025-07-02 06:41:16.260 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.260 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.260 alo = 27, ahi = 1101
2025-07-02 06:41:16.260 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.260 blo = 27, bhi = 1101
2025-07-02 06:41:16.260
2025-07-02 06:41:16.260     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.260         r"""
2025-07-02 06:41:16.260         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.260         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.260         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.260         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.260
2025-07-02 06:41:16.260         Example:
2025-07-02 06:41:16.260
2025-07-02 06:41:16.260         >>> d = Differ()
2025-07-02 06:41:16.260         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.260         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.260         >>> print(''.join(results), end="")
2025-07-02 06:41:16.261         - abcDefghiJkl
2025-07-02 06:41:16.261         + abcdefGhijkl
2025-07-02 06:41:16.261         """
2025-07-02 06:41:16.261
2025-07-02 06:41:16.261         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.261         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.261         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.261         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.261         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.261
2025-07-02 06:41:16.261         # search for the pair that matches best without being identical
2025-07-02 06:41:16.261         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.261         # on junk -- unless we have to)
2025-07-02 06:41:16.261         for j in range(blo, bhi):
2025-07-02 06:41:16.261             bj = b[j]
2025-07-02 06:41:16.261             cruncher.set_seq2(bj)
2025-07-02 06:41:16.261             for i in range(alo, ahi):
2025-07-02 06:41:16.261                 ai = a[i]
2025-07-02 06:41:16.261                 if ai == bj:
2025-07-02 06:41:16.262                     if eqi is None:
2025-07-02 06:41:16.262                         eqi, eqj = i, j
2025-07-02 06:41:16.262                     continue
2025-07-02 06:41:16.262                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.262                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.262                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.262                 # compares by a factor of 3.
2025-07-02 06:41:16.262                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.262                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.262                 # of the computation is cached by cruncher
2025-07-02 06:41:16.262                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.262                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.262                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.262                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.262         if best_ratio < cutoff:
2025-07-02 06:41:16.262             # no non-identical "pretty close" pair
2025-07-02 06:41:16.262             if eqi is None:
2025-07-02 06:41:16.262                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.262                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.262                 return
2025-07-02 06:41:16.263             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.263             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.263         else:
2025-07-02 06:41:16.263             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.263             eqi = None
2025-07-02 06:41:16.263
2025-07-02 06:41:16.263         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.263         # identical
2025-07-02 06:41:16.263
2025-07-02 06:41:16.263         # pump out diffs from before the synch point
2025-07-02 06:41:16.263         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.263
2025-07-02 06:41:16.263         # do intraline marking on the synch pair
2025-07-02 06:41:16.263         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.263         if eqi is None:
2025-07-02 06:41:16.263             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.263             atags = btags = ""
2025-07-02 06:41:16.263             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.263             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.263                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.263                 if tag == 'replace':
2025-07-02 06:41:16.264                     atags += '^' * la
2025-07-02 06:41:16.264                     btags += '^' * lb
2025-07-02 06:41:16.264                 elif tag == 'delete':
2025-07-02 06:41:16.264                     atags += '-' * la
2025-07-02 06:41:16.264                 elif tag == 'insert':
2025-07-02 06:41:16.264                     btags += '+' * lb
2025-07-02 06:41:16.264                 elif tag == 'equal':
2025-07-02 06:41:16.264                     atags += ' ' * la
2025-07-02 06:41:16.264                     btags += ' ' * lb
2025-07-02 06:41:16.264                 else:
2025-07-02 06:41:16.264                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.264             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.264         else:
2025-07-02 06:41:16.264             # the synch pair is identical
2025-07-02 06:41:16.264             yield '  ' + aelt
2025-07-02 06:41:16.264
2025-07-02 06:41:16.264         # pump out diffs from after the synch point
2025-07-02 06:41:16.264 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.264
2025-07-02 06:41:16.264 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.264 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.265
2025-07-02 06:41:16.265 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.265 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.265 alo = 28, ahi = 1101
2025-07-02 06:41:16.265 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.265 blo = 28, bhi = 1101
2025-07-02 06:41:16.265
2025-07-02 06:41:16.265     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.265         g = []
2025-07-02 06:41:16.265         if alo < ahi:
2025-07-02 06:41:16.265             if blo < bhi:
2025-07-02 06:41:16.265                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.265             else:
2025-07-02 06:41:16.265                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.265         elif blo < bhi:
2025-07-02 06:41:16.265             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.265
2025-07-02 06:41:16.265 >       yield from g
2025-07-02 06:41:16.265
2025-07-02 06:41:16.266 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.266 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.266
2025-07-02 06:41:16.266 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.266 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.266 alo = 28, ahi = 1101
2025-07-02 06:41:16.266 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.266 blo = 28, bhi = 1101
2025-07-02 06:41:16.266
2025-07-02 06:41:16.266     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.266         r"""
2025-07-02 06:41:16.266         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.266         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.266         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.266         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.266
2025-07-02 06:41:16.266         Example:
2025-07-02 06:41:16.266
2025-07-02 06:41:16.266         >>> d = Differ()
2025-07-02 06:41:16.267         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.267         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.267         >>> print(''.join(results), end="")
2025-07-02 06:41:16.267         - abcDefghiJkl
2025-07-02 06:41:16.267         + abcdefGhijkl
2025-07-02 06:41:16.267         """
2025-07-02 06:41:16.267
2025-07-02 06:41:16.267         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.267         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.267         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.267         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.267         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.267
2025-07-02 06:41:16.267         # search for the pair that matches best without being identical
2025-07-02 06:41:16.267         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.267         # on junk -- unless we have to)
2025-07-02 06:41:16.267         for j in range(blo, bhi):
2025-07-02 06:41:16.267             bj = b[j]
2025-07-02 06:41:16.268             cruncher.set_seq2(bj)
2025-07-02 06:41:16.268             for i in range(alo, ahi):
2025-07-02 06:41:16.268                 ai = a[i]
2025-07-02 06:41:16.268                 if ai == bj:
2025-07-02 06:41:16.268                     if eqi is None:
2025-07-02 06:41:16.268                         eqi, eqj = i, j
2025-07-02 06:41:16.268                     continue
2025-07-02 06:41:16.268                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.268                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.268                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.268                 # compares by a factor of 3.
2025-07-02 06:41:16.268                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.268                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.268                 # of the computation is cached by cruncher
2025-07-02 06:41:16.268                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.268                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.268                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.268                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.268         if best_ratio < cutoff:
2025-07-02 06:41:16.269             # no non-identical "pretty close" pair
2025-07-02 06:41:16.269             if eqi is None:
2025-07-02 06:41:16.269                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.269                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.269                 return
2025-07-02 06:41:16.269             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.269             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.269         else:
2025-07-02 06:41:16.269             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.269             eqi = None
2025-07-02 06:41:16.269
2025-07-02 06:41:16.269         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.269         # identical
2025-07-02 06:41:16.269
2025-07-02 06:41:16.269         # pump out diffs from before the synch point
2025-07-02 06:41:16.269         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.269
2025-07-02 06:41:16.269         # do intraline marking on the synch pair
2025-07-02 06:41:16.269         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.269         if eqi is None:
2025-07-02 06:41:16.269             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.270             atags = btags = ""
2025-07-02 06:41:16.270             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.270             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.270                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.270                 if tag == 'replace':
2025-07-02 06:41:16.270                     atags += '^' * la
2025-07-02 06:41:16.270                     btags += '^' * lb
2025-07-02 06:41:16.270                 elif tag == 'delete':
2025-07-02 06:41:16.270                     atags += '-' * la
2025-07-02 06:41:16.270                 elif tag == 'insert':
2025-07-02 06:41:16.270                     btags += '+' * lb
2025-07-02 06:41:16.270                 elif tag == 'equal':
2025-07-02 06:41:16.270                     atags += ' ' * la
2025-07-02 06:41:16.270                     btags += ' ' * lb
2025-07-02 06:41:16.270                 else:
2025-07-02 06:41:16.270                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.270             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.270         else:
2025-07-02 06:41:16.271             # the synch pair is identical
2025-07-02 06:41:16.271             yield '  ' + aelt
2025-07-02 06:41:16.271
2025-07-02 06:41:16.271         # pump out diffs from after the synch point
2025-07-02 06:41:16.271 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.271
2025-07-02 06:41:16.271 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.271 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.271
2025-07-02 06:41:16.271 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.271 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.271 alo = 29, ahi = 1101
2025-07-02 06:41:16.271 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.271 blo = 29, bhi = 1101
2025-07-02 06:41:16.271
2025-07-02 06:41:16.271     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.271         g = []
2025-07-02 06:41:16.271         if alo < ahi:
2025-07-02 06:41:16.271             if blo < bhi:
2025-07-02 06:41:16.272                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.272             else:
2025-07-02 06:41:16.272                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.272         elif blo < bhi:
2025-07-02 06:41:16.272             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.272
2025-07-02 06:41:16.272 >       yield from g
2025-07-02 06:41:16.272
2025-07-02 06:41:16.272 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.272 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.272
2025-07-02 06:41:16.272 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.272 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.272 alo = 29, ahi = 1101
2025-07-02 06:41:16.272 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.272 blo = 29, bhi = 1101
2025-07-02 06:41:16.272
2025-07-02 06:41:16.272     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.272         r"""
2025-07-02 06:41:16.272         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.273         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.273         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.273         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.273
2025-07-02 06:41:16.273         Example:
2025-07-02 06:41:16.273
2025-07-02 06:41:16.273         >>> d = Differ()
2025-07-02 06:41:16.273         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.273         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.273         >>> print(''.join(results), end="")
2025-07-02 06:41:16.273         - abcDefghiJkl
2025-07-02 06:41:16.273         + abcdefGhijkl
2025-07-02 06:41:16.273         """
2025-07-02 06:41:16.273
2025-07-02 06:41:16.273         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.273         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.273         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.273         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.274         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.274
2025-07-02 06:41:16.274         # search for the pair that matches best without being identical
2025-07-02 06:41:16.274         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.274         # on junk -- unless we have to)
2025-07-02 06:41:16.274         for j in range(blo, bhi):
2025-07-02 06:41:16.274             bj = b[j]
2025-07-02 06:41:16.274             cruncher.set_seq2(bj)
2025-07-02 06:41:16.274             for i in range(alo, ahi):
2025-07-02 06:41:16.274                 ai = a[i]
2025-07-02 06:41:16.274                 if ai == bj:
2025-07-02 06:41:16.274                     if eqi is None:
2025-07-02 06:41:16.274                         eqi, eqj = i, j
2025-07-02 06:41:16.274                     continue
2025-07-02 06:41:16.274                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.274                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.274                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.274                 # compares by a factor of 3.
2025-07-02 06:41:16.274                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.275                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.275                 # of the computation is cached by cruncher
2025-07-02 06:41:16.275                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.275                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.275                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.275                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.275         if best_ratio < cutoff:
2025-07-02 06:41:16.275             # no non-identical "pretty close" pair
2025-07-02 06:41:16.275             if eqi is None:
2025-07-02 06:41:16.275                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.275                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.275                 return
2025-07-02 06:41:16.275             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.275             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.275         else:
2025-07-02 06:41:16.275             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.275             eqi = None
2025-07-02 06:41:16.275
2025-07-02 06:41:16.275         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.276         # identical
2025-07-02 06:41:16.276
2025-07-02 06:41:16.276         # pump out diffs from before the synch point
2025-07-02 06:41:16.276         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.276
2025-07-02 06:41:16.276         # do intraline marking on the synch pair
2025-07-02 06:41:16.276         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.276         if eqi is None:
2025-07-02 06:41:16.276             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.276             atags = btags = ""
2025-07-02 06:41:16.276             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.276             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.276                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.276                 if tag == 'replace':
2025-07-02 06:41:16.276                     atags += '^' * la
2025-07-02 06:41:16.276                     btags += '^' * lb
2025-07-02 06:41:16.276                 elif tag == 'delete':
2025-07-02 06:41:16.276                     atags += '-' * la
2025-07-02 06:41:16.276                 elif tag == 'insert':
2025-07-02 06:41:16.277                     btags += '+' * lb
2025-07-02 06:41:16.277                 elif tag == 'equal':
2025-07-02 06:41:16.277                     atags += ' ' * la
2025-07-02 06:41:16.277                     btags += ' ' * lb
2025-07-02 06:41:16.277                 else:
2025-07-02 06:41:16.277                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.277             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.277         else:
2025-07-02 06:41:16.277             # the synch pair is identical
2025-07-02 06:41:16.277             yield '  ' + aelt
2025-07-02 06:41:16.277
2025-07-02 06:41:16.277         # pump out diffs from after the synch point
2025-07-02 06:41:16.277 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.277
2025-07-02 06:41:16.277 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.277 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.277
2025-07-02 06:41:16.277 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.277 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.277 alo = 30, ahi = 1101
2025-07-02 06:41:16.278 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.278 blo = 30, bhi = 1101
2025-07-02 06:41:16.278
2025-07-02 06:41:16.278     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.278         g = []
2025-07-02 06:41:16.278         if alo < ahi:
2025-07-02 06:41:16.278             if blo < bhi:
2025-07-02 06:41:16.278                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.278             else:
2025-07-02 06:41:16.278                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.278         elif blo < bhi:
2025-07-02 06:41:16.278             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.278
2025-07-02 06:41:16.278 >       yield from g
2025-07-02 06:41:16.278
2025-07-02 06:41:16.278 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.278 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.278
2025-07-02 06:41:16.278 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.278 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.279 alo = 30, ahi = 1101
2025-07-02 06:41:16.279 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.279 blo = 30, bhi = 1101
2025-07-02 06:41:16.279
2025-07-02 06:41:16.279     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.279         r"""
2025-07-02 06:41:16.279         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.279         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.279         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.279         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.279
2025-07-02 06:41:16.279         Example:
2025-07-02 06:41:16.279
2025-07-02 06:41:16.279         >>> d = Differ()
2025-07-02 06:41:16.279         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.279         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.279         >>> print(''.join(results), end="")
2025-07-02 06:41:16.279         - abcDefghiJkl
2025-07-02 06:41:16.279         + abcdefGhijkl
2025-07-02 06:41:16.280         """
2025-07-02 06:41:16.280
2025-07-02 06:41:16.280         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.280         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.280         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.280         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.280         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.280
2025-07-02 06:41:16.280         # search for the pair that matches best without being identical
2025-07-02 06:41:16.280         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.280         # on junk -- unless we have to)
2025-07-02 06:41:16.280         for j in range(blo, bhi):
2025-07-02 06:41:16.280             bj = b[j]
2025-07-02 06:41:16.280             cruncher.set_seq2(bj)
2025-07-02 06:41:16.280             for i in range(alo, ahi):
2025-07-02 06:41:16.280                 ai = a[i]
2025-07-02 06:41:16.280                 if ai == bj:
2025-07-02 06:41:16.280                     if eqi is None:
2025-07-02 06:41:16.280                         eqi, eqj = i, j
2025-07-02 06:41:16.280                     continue
2025-07-02 06:41:16.281                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.281                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.281                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.281                 # compares by a factor of 3.
2025-07-02 06:41:16.281                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.281                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.281                 # of the computation is cached by cruncher
2025-07-02 06:41:16.281                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.281                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.281                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.281                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.281         if best_ratio < cutoff:
2025-07-02 06:41:16.281             # no non-identical "pretty close" pair
2025-07-02 06:41:16.281             if eqi is None:
2025-07-02 06:41:16.281                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.281                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.281                 return
2025-07-02 06:41:16.281             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.281             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.281         else:
2025-07-02 06:41:16.282             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.282             eqi = None
2025-07-02 06:41:16.282
2025-07-02 06:41:16.282         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.282         # identical
2025-07-02 06:41:16.282
2025-07-02 06:41:16.282         # pump out diffs from before the synch point
2025-07-02 06:41:16.282         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.282
2025-07-02 06:41:16.282         # do intraline marking on the synch pair
2025-07-02 06:41:16.282         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.282         if eqi is None:
2025-07-02 06:41:16.282             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.282             atags = btags = ""
2025-07-02 06:41:16.282             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.282             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.282                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.282                 if tag == 'replace':
2025-07-02 06:41:16.282                     atags += '^' * la
2025-07-02 06:41:16.282                     btags += '^' * lb
2025-07-02 06:41:16.282                 elif tag == 'delete':
2025-07-02 06:41:16.283                     atags += '-' * la
2025-07-02 06:41:16.283                 elif tag == 'insert':
2025-07-02 06:41:16.283                     btags += '+' * lb
2025-07-02 06:41:16.283                 elif tag == 'equal':
2025-07-02 06:41:16.283                     atags += ' ' * la
2025-07-02 06:41:16.283                     btags += ' ' * lb
2025-07-02 06:41:16.283                 else:
2025-07-02 06:41:16.283                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.283             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.283         else:
2025-07-02 06:41:16.283             # the synch pair is identical
2025-07-02 06:41:16.283             yield '  ' + aelt
2025-07-02 06:41:16.283
2025-07-02 06:41:16.283         # pump out diffs from after the synch point
2025-07-02 06:41:16.283 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.283
2025-07-02 06:41:16.283 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.283 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.284
2025-07-02 06:41:16.284 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.284 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.284 alo = 31, ahi = 1101
2025-07-02 06:41:16.284 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.284 blo = 31, bhi = 1101
2025-07-02 06:41:16.284
2025-07-02 06:41:16.284     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.284         g = []
2025-07-02 06:41:16.284         if alo < ahi:
2025-07-02 06:41:16.284             if blo < bhi:
2025-07-02 06:41:16.284                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.284             else:
2025-07-02 06:41:16.284                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.284         elif blo < bhi:
2025-07-02 06:41:16.284             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.284
2025-07-02 06:41:16.284 >       yield from g
2025-07-02 06:41:16.284
2025-07-02 06:41:16.284 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.285 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.285
2025-07-02 06:41:16.285 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.285 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.285 alo = 31, ahi = 1101
2025-07-02 06:41:16.285 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.285 blo = 31, bhi = 1101
2025-07-02 06:41:16.285
2025-07-02 06:41:16.285     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.285         r"""
2025-07-02 06:41:16.285         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.285         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.285         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.285         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.285
2025-07-02 06:41:16.285         Example:
2025-07-02 06:41:16.285
2025-07-02 06:41:16.285         >>> d = Differ()
2025-07-02 06:41:16.285         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.286         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.286         >>> print(''.join(results), end="")
2025-07-02 06:41:16.286         - abcDefghiJkl
2025-07-02 06:41:16.286         + abcdefGhijkl
2025-07-02 06:41:16.286         """
2025-07-02 06:41:16.286
2025-07-02 06:41:16.286         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.286         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.286         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.286         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.286         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.286
2025-07-02 06:41:16.286         # search for the pair that matches best without being identical
2025-07-02 06:41:16.286         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.286         # on junk -- unless we have to)
2025-07-02 06:41:16.286         for j in range(blo, bhi):
2025-07-02 06:41:16.286             bj = b[j]
2025-07-02 06:41:16.287             cruncher.set_seq2(bj)
2025-07-02 06:41:16.287             for i in range(alo, ahi):
2025-07-02 06:41:16.287                 ai = a[i]
2025-07-02 06:41:16.287                 if ai == bj:
2025-07-02 06:41:16.287                     if eqi is None:
2025-07-02 06:41:16.287                         eqi, eqj = i, j
2025-07-02 06:41:16.287                     continue
2025-07-02 06:41:16.287                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.287                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.287                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.287                 # compares by a factor of 3.
2025-07-02 06:41:16.287                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.287                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.287                 # of the computation is cached by cruncher
2025-07-02 06:41:16.287                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.287                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.287                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.287                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.287         if best_ratio < cutoff:
2025-07-02 06:41:16.287             # no non-identical "pretty close" pair
2025-07-02 06:41:16.288             if eqi is None:
2025-07-02 06:41:16.288                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.288                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.288                 return
2025-07-02 06:41:16.288             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.288             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.288         else:
2025-07-02 06:41:16.288             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.288             eqi = None
2025-07-02 06:41:16.288
2025-07-02 06:41:16.288         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.288         # identical
2025-07-02 06:41:16.288
2025-07-02 06:41:16.288         # pump out diffs from before the synch point
2025-07-02 06:41:16.288         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.288
2025-07-02 06:41:16.288         # do intraline marking on the synch pair
2025-07-02 06:41:16.288         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.288         if eqi is None:
2025-07-02 06:41:16.288             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.289             atags = btags = ""
2025-07-02 06:41:16.289             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.289             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.289                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.289                 if tag == 'replace':
2025-07-02 06:41:16.289                     atags += '^' * la
2025-07-02 06:41:16.289                     btags += '^' * lb
2025-07-02 06:41:16.289                 elif tag == 'delete':
2025-07-02 06:41:16.289                     atags += '-' * la
2025-07-02 06:41:16.289                 elif tag == 'insert':
2025-07-02 06:41:16.289                     btags += '+' * lb
2025-07-02 06:41:16.289                 elif tag == 'equal':
2025-07-02 06:41:16.289                     atags += ' ' * la
2025-07-02 06:41:16.289                     btags += ' ' * lb
2025-07-02 06:41:16.289                 else:
2025-07-02 06:41:16.289                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.289             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.289         else:
2025-07-02 06:41:16.289             # the synch pair is identical
2025-07-02 06:41:16.289             yield '  ' + aelt
2025-07-02 06:41:16.290
2025-07-02 06:41:16.290         # pump out diffs from after the synch point
2025-07-02 06:41:16.290 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.290
2025-07-02 06:41:16.290 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.290 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.290
2025-07-02 06:41:16.290 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.290 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.290 alo = 32, ahi = 1101
2025-07-02 06:41:16.290 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.290 blo = 32, bhi = 1101
2025-07-02 06:41:16.290
2025-07-02 06:41:16.290     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.290         g = []
2025-07-02 06:41:16.290         if alo < ahi:
2025-07-02 06:41:16.290             if blo < bhi:
2025-07-02 06:41:16.290                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.290             else:
2025-07-02 06:41:16.291                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.291         elif blo < bhi:
2025-07-02 06:41:16.291             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.291
2025-07-02 06:41:16.291 >       yield from g
2025-07-02 06:41:16.291
2025-07-02 06:41:16.291 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.291 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.291
2025-07-02 06:41:16.291 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.291 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.291 alo = 32, ahi = 1101
2025-07-02 06:41:16.291 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.291 blo = 32, bhi = 1101
2025-07-02 06:41:16.291
2025-07-02 06:41:16.291     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.291         r"""
2025-07-02 06:41:16.291         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.292         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.292         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.292         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.292
2025-07-02 06:41:16.292         Example:
2025-07-02 06:41:16.292
2025-07-02 06:41:16.292         >>> d = Differ()
2025-07-02 06:41:16.292         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.292         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.292         >>> print(''.join(results), end="")
2025-07-02 06:41:16.292         - abcDefghiJkl
2025-07-02 06:41:16.292         + abcdefGhijkl
2025-07-02 06:41:16.292         """
2025-07-02 06:41:16.292
2025-07-02 06:41:16.292         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.292         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.292         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.293         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.293         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.293
2025-07-02 06:41:16.293         # search for the pair that matches best without being identical
2025-07-02 06:41:16.293         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.293         # on junk -- unless we have to)
2025-07-02 06:41:16.293         for j in range(blo, bhi):
2025-07-02 06:41:16.293             bj = b[j]
2025-07-02 06:41:16.293             cruncher.set_seq2(bj)
2025-07-02 06:41:16.293             for i in range(alo, ahi):
2025-07-02 06:41:16.293                 ai = a[i]
2025-07-02 06:41:16.293                 if ai == bj:
2025-07-02 06:41:16.293                     if eqi is None:
2025-07-02 06:41:16.293                         eqi, eqj = i, j
2025-07-02 06:41:16.293                     continue
2025-07-02 06:41:16.293                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.293                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.293                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.293                 # compares by a factor of 3.
2025-07-02 06:41:16.293                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.294                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.294                 # of the computation is cached by cruncher
2025-07-02 06:41:16.294                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.294                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.294                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.294                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.294         if best_ratio < cutoff:
2025-07-02 06:41:16.294             # no non-identical "pretty close" pair
2025-07-02 06:41:16.294             if eqi is None:
2025-07-02 06:41:16.294                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.294                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.294                 return
2025-07-02 06:41:16.294             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.294             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.294         else:
2025-07-02 06:41:16.294             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.294             eqi = None
2025-07-02 06:41:16.294
2025-07-02 06:41:16.294         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.295         # identical
2025-07-02 06:41:16.295
2025-07-02 06:41:16.295         # pump out diffs from before the synch point
2025-07-02 06:41:16.295         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.295
2025-07-02 06:41:16.295         # do intraline marking on the synch pair
2025-07-02 06:41:16.295         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.295         if eqi is None:
2025-07-02 06:41:16.295             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.295             atags = btags = ""
2025-07-02 06:41:16.295             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.295             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.295                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.295                 if tag == 'replace':
2025-07-02 06:41:16.295                     atags += '^' * la
2025-07-02 06:41:16.295                     btags += '^' * lb
2025-07-02 06:41:16.295                 elif tag == 'delete':
2025-07-02 06:41:16.295                     atags += '-' * la
2025-07-02 06:41:16.295                 elif tag == 'insert':
2025-07-02 06:41:16.295                     btags += '+' * lb
2025-07-02 06:41:16.295                 elif tag == 'equal':
2025-07-02 06:41:16.296                     atags += ' ' * la
2025-07-02 06:41:16.296                     btags += ' ' * lb
2025-07-02 06:41:16.296                 else:
2025-07-02 06:41:16.296                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.296             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.296         else:
2025-07-02 06:41:16.296             # the synch pair is identical
2025-07-02 06:41:16.296             yield '  ' + aelt
2025-07-02 06:41:16.296
2025-07-02 06:41:16.296         # pump out diffs from after the synch point
2025-07-02 06:41:16.296 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.296
2025-07-02 06:41:16.296 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.296 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.296
2025-07-02 06:41:16.296 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.296 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.296 alo = 33, ahi = 1101
2025-07-02 06:41:16.296 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.296 blo = 33, bhi = 1101
2025-07-02 06:41:16.297
2025-07-02 06:41:16.297     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.297         g = []
2025-07-02 06:41:16.297         if alo < ahi:
2025-07-02 06:41:16.297             if blo < bhi:
2025-07-02 06:41:16.297                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.297             else:
2025-07-02 06:41:16.297                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.297         elif blo < bhi:
2025-07-02 06:41:16.297             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.297
2025-07-02 06:41:16.297 >       yield from g
2025-07-02 06:41:16.297
2025-07-02 06:41:16.297 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.297 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.297
2025-07-02 06:41:16.297 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.297 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.297 alo = 33, ahi = 1101
2025-07-02 06:41:16.297 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.298 blo = 33, bhi = 1101
2025-07-02 06:41:16.298
2025-07-02 06:41:16.298     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.298         r"""
2025-07-02 06:41:16.298         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.298         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.298         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.298         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.298
2025-07-02 06:41:16.298         Example:
2025-07-02 06:41:16.298
2025-07-02 06:41:16.298         >>> d = Differ()
2025-07-02 06:41:16.298         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.298         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.298         >>> print(''.join(results), end="")
2025-07-02 06:41:16.298         - abcDefghiJkl
2025-07-02 06:41:16.298         + abcdefGhijkl
2025-07-02 06:41:16.298         """
2025-07-02 06:41:16.299
2025-07-02 06:41:16.299         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.299         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.299         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.299         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.299         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.299
2025-07-02 06:41:16.299         # search for the pair that matches best without being identical
2025-07-02 06:41:16.299         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.299         # on junk -- unless we have to)
2025-07-02 06:41:16.299         for j in range(blo, bhi):
2025-07-02 06:41:16.299             bj = b[j]
2025-07-02 06:41:16.299             cruncher.set_seq2(bj)
2025-07-02 06:41:16.299             for i in range(alo, ahi):
2025-07-02 06:41:16.299                 ai = a[i]
2025-07-02 06:41:16.299                 if ai == bj:
2025-07-02 06:41:16.299                     if eqi is None:
2025-07-02 06:41:16.299                         eqi, eqj = i, j
2025-07-02 06:41:16.299                     continue
2025-07-02 06:41:16.299                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.299                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.300                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.300                 # compares by a factor of 3.
2025-07-02 06:41:16.300                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.300                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.300                 # of the computation is cached by cruncher
2025-07-02 06:41:16.300                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.300                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.300                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.300                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.300         if best_ratio < cutoff:
2025-07-02 06:41:16.300             # no non-identical "pretty close" pair
2025-07-02 06:41:16.300             if eqi is None:
2025-07-02 06:41:16.300                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.300                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.300                 return
2025-07-02 06:41:16.300             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.300             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.300         else:
2025-07-02 06:41:16.300             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.301             eqi = None
2025-07-02 06:41:16.301
2025-07-02 06:41:16.301         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.301         # identical
2025-07-02 06:41:16.301
2025-07-02 06:41:16.301         # pump out diffs from before the synch point
2025-07-02 06:41:16.301         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.301
2025-07-02 06:41:16.301         # do intraline marking on the synch pair
2025-07-02 06:41:16.301         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.301         if eqi is None:
2025-07-02 06:41:16.301             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.301             atags = btags = ""
2025-07-02 06:41:16.301             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.301             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.301                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.301                 if tag == 'replace':
2025-07-02 06:41:16.301                     atags += '^' * la
2025-07-02 06:41:16.301                     btags += '^' * lb
2025-07-02 06:41:16.302                 elif tag == 'delete':
2025-07-02 06:41:16.302                     atags += '-' * la
2025-07-02 06:41:16.302                 elif tag == 'insert':
2025-07-02 06:41:16.302                     btags += '+' * lb
2025-07-02 06:41:16.302                 elif tag == 'equal':
2025-07-02 06:41:16.302                     atags += ' ' * la
2025-07-02 06:41:16.302                     btags += ' ' * lb
2025-07-02 06:41:16.302                 else:
2025-07-02 06:41:16.302                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.302             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.302         else:
2025-07-02 06:41:16.302             # the synch pair is identical
2025-07-02 06:41:16.302             yield '  ' + aelt
2025-07-02 06:41:16.302
2025-07-02 06:41:16.302         # pump out diffs from after the synch point
2025-07-02 06:41:16.302 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.302
2025-07-02 06:41:16.302 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.302 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.303
2025-07-02 06:41:16.303 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.303 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.303 alo = 34, ahi = 1101
2025-07-02 06:41:16.303 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.303 blo = 34, bhi = 1101
2025-07-02 06:41:16.303
2025-07-02 06:41:16.303     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.303         g = []
2025-07-02 06:41:16.303         if alo < ahi:
2025-07-02 06:41:16.303             if blo < bhi:
2025-07-02 06:41:16.303                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.303             else:
2025-07-02 06:41:16.303                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.303         elif blo < bhi:
2025-07-02 06:41:16.303             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.303
2025-07-02 06:41:16.303 >       yield from g
2025-07-02 06:41:16.303
2025-07-02 06:41:16.303 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.304 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.304
2025-07-02 06:41:16.304 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.304 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.304 alo = 34, ahi = 1101
2025-07-02 06:41:16.304 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.304 blo = 34, bhi = 1101
2025-07-02 06:41:16.304
2025-07-02 06:41:16.304     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.304         r"""
2025-07-02 06:41:16.304         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.304         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.304         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.304         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.304
2025-07-02 06:41:16.304         Example:
2025-07-02 06:41:16.304
2025-07-02 06:41:16.304         >>> d = Differ()
2025-07-02 06:41:16.304         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.304         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.305         >>> print(''.join(results), end="")
2025-07-02 06:41:16.305         - abcDefghiJkl
2025-07-02 06:41:16.305         + abcdefGhijkl
2025-07-02 06:41:16.305         """
2025-07-02 06:41:16.305
2025-07-02 06:41:16.305         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.305         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.305         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.305         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.305         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.305
2025-07-02 06:41:16.305         # search for the pair that matches best without being identical
2025-07-02 06:41:16.305         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.305         # on junk -- unless we have to)
2025-07-02 06:41:16.305         for j in range(blo, bhi):
2025-07-02 06:41:16.305             bj = b[j]
2025-07-02 06:41:16.305             cruncher.set_seq2(bj)
2025-07-02 06:41:16.305             for i in range(alo, ahi):
2025-07-02 06:41:16.306                 ai = a[i]
2025-07-02 06:41:16.306                 if ai == bj:
2025-07-02 06:41:16.306                     if eqi is None:
2025-07-02 06:41:16.306                         eqi, eqj = i, j
2025-07-02 06:41:16.306                     continue
2025-07-02 06:41:16.306                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.306                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.306                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.306                 # compares by a factor of 3.
2025-07-02 06:41:16.306                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.306                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.306                 # of the computation is cached by cruncher
2025-07-02 06:41:16.306                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.306                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.306                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.306                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.306         if best_ratio < cutoff:
2025-07-02 06:41:16.306             # no non-identical "pretty close" pair
2025-07-02 06:41:16.306             if eqi is None:
2025-07-02 06:41:16.306                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.307                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.307                 return
2025-07-02 06:41:16.307             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.307             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.307         else:
2025-07-02 06:41:16.307             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.307             eqi = None
2025-07-02 06:41:16.307
2025-07-02 06:41:16.307         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.307         # identical
2025-07-02 06:41:16.307
2025-07-02 06:41:16.307         # pump out diffs from before the synch point
2025-07-02 06:41:16.307         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.307
2025-07-02 06:41:16.307         # do intraline marking on the synch pair
2025-07-02 06:41:16.307         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.307         if eqi is None:
2025-07-02 06:41:16.307             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.307             atags = btags = ""
2025-07-02 06:41:16.307             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.307             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.308                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.308                 if tag == 'replace':
2025-07-02 06:41:16.308                     atags += '^' * la
2025-07-02 06:41:16.308                     btags += '^' * lb
2025-07-02 06:41:16.308                 elif tag == 'delete':
2025-07-02 06:41:16.308                     atags += '-' * la
2025-07-02 06:41:16.308                 elif tag == 'insert':
2025-07-02 06:41:16.308                     btags += '+' * lb
2025-07-02 06:41:16.308                 elif tag == 'equal':
2025-07-02 06:41:16.308                     atags += ' ' * la
2025-07-02 06:41:16.308                     btags += ' ' * lb
2025-07-02 06:41:16.308                 else:
2025-07-02 06:41:16.308                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.308             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.308         else:
2025-07-02 06:41:16.308             # the synch pair is identical
2025-07-02 06:41:16.308             yield '  ' + aelt
2025-07-02 06:41:16.308
2025-07-02 06:41:16.308         # pump out diffs from after the synch point
2025-07-02 06:41:16.308 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.309
2025-07-02 06:41:16.309 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.309 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.309
2025-07-02 06:41:16.309 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.309 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.309 alo = 35, ahi = 1101
2025-07-02 06:41:16.309 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.309 blo = 35, bhi = 1101
2025-07-02 06:41:16.309
2025-07-02 06:41:16.309     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.309         g = []
2025-07-02 06:41:16.309         if alo < ahi:
2025-07-02 06:41:16.309             if blo < bhi:
2025-07-02 06:41:16.309                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.309             else:
2025-07-02 06:41:16.309                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.309         elif blo < bhi:
2025-07-02 06:41:16.310             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.310
2025-07-02 06:41:16.310 >       yield from g
2025-07-02 06:41:16.310
2025-07-02 06:41:16.310 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.310 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.310
2025-07-02 06:41:16.310 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.310 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.310 alo = 35, ahi = 1101
2025-07-02 06:41:16.310 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.310 blo = 35, bhi = 1101
2025-07-02 06:41:16.310
2025-07-02 06:41:16.310     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.310         r"""
2025-07-02 06:41:16.310         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.310         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.310         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.310         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.311
2025-07-02 06:41:16.311         Example:
2025-07-02 06:41:16.311
2025-07-02 06:41:16.311         >>> d = Differ()
2025-07-02 06:41:16.311         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.311         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.311         >>> print(''.join(results), end="")
2025-07-02 06:41:16.311         - abcDefghiJkl
2025-07-02 06:41:16.311         + abcdefGhijkl
2025-07-02 06:41:16.311         """
2025-07-02 06:41:16.311
2025-07-02 06:41:16.311         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.311         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.311         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.311         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.311         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.311
2025-07-02 06:41:16.311         # search for the pair that matches best without being identical
2025-07-02 06:41:16.312         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.312         # on junk -- unless we have to)
2025-07-02 06:41:16.312         for j in range(blo, bhi):
2025-07-02 06:41:16.312             bj = b[j]
2025-07-02 06:41:16.312             cruncher.set_seq2(bj)
2025-07-02 06:41:16.312             for i in range(alo, ahi):
2025-07-02 06:41:16.312                 ai = a[i]
2025-07-02 06:41:16.312                 if ai == bj:
2025-07-02 06:41:16.312                     if eqi is None:
2025-07-02 06:41:16.312                         eqi, eqj = i, j
2025-07-02 06:41:16.312                     continue
2025-07-02 06:41:16.312                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.312                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.312                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.312                 # compares by a factor of 3.
2025-07-02 06:41:16.312                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.312                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.312                 # of the computation is cached by cruncher
2025-07-02 06:41:16.312                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.312                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.313                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.313                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.313         if best_ratio < cutoff:
2025-07-02 06:41:16.313             # no non-identical "pretty close" pair
2025-07-02 06:41:16.313             if eqi is None:
2025-07-02 06:41:16.313                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.313                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.313                 return
2025-07-02 06:41:16.313             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.313             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.313         else:
2025-07-02 06:41:16.313             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.313             eqi = None
2025-07-02 06:41:16.313
2025-07-02 06:41:16.313         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.313         # identical
2025-07-02 06:41:16.313
2025-07-02 06:41:16.313         # pump out diffs from before the synch point
2025-07-02 06:41:16.313         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.313
2025-07-02 06:41:16.313         # do intraline marking on the synch pair
2025-07-02 06:41:16.314         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.314         if eqi is None:
2025-07-02 06:41:16.314             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.314             atags = btags = ""
2025-07-02 06:41:16.314             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.314             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.314                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.314                 if tag == 'replace':
2025-07-02 06:41:16.314                     atags += '^' * la
2025-07-02 06:41:16.314                     btags += '^' * lb
2025-07-02 06:41:16.314                 elif tag == 'delete':
2025-07-02 06:41:16.314                     atags += '-' * la
2025-07-02 06:41:16.314                 elif tag == 'insert':
2025-07-02 06:41:16.314                     btags += '+' * lb
2025-07-02 06:41:16.314                 elif tag == 'equal':
2025-07-02 06:41:16.314                     atags += ' ' * la
2025-07-02 06:41:16.314                     btags += ' ' * lb
2025-07-02 06:41:16.314                 else:
2025-07-02 06:41:16.314                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.314             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.315         else:
2025-07-02 06:41:16.315             # the synch pair is identical
2025-07-02 06:41:16.315             yield '  ' + aelt
2025-07-02 06:41:16.315
2025-07-02 06:41:16.315         # pump out diffs from after the synch point
2025-07-02 06:41:16.315 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.315
2025-07-02 06:41:16.315 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.315 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.315
2025-07-02 06:41:16.315 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.315 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.315 alo = 36, ahi = 1101
2025-07-02 06:41:16.315 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.315 blo = 36, bhi = 1101
2025-07-02 06:41:16.315
2025-07-02 06:41:16.315     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.315         g = []
2025-07-02 06:41:16.315         if alo < ahi:
2025-07-02 06:41:16.315             if blo < bhi:
2025-07-02 06:41:16.315                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.316             else:
2025-07-02 06:41:16.316                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.316         elif blo < bhi:
2025-07-02 06:41:16.316             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.316
2025-07-02 06:41:16.316 >       yield from g
2025-07-02 06:41:16.316
2025-07-02 06:41:16.316 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.316 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.316
2025-07-02 06:41:16.316 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.316 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.316 alo = 36, ahi = 1101
2025-07-02 06:41:16.316 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.316 blo = 36, bhi = 1101
2025-07-02 06:41:16.316
2025-07-02 06:41:16.316     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.316         r"""
2025-07-02 06:41:16.316         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.316         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.317         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.317         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.317
2025-07-02 06:41:16.317         Example:
2025-07-02 06:41:16.317
2025-07-02 06:41:16.317         >>> d = Differ()
2025-07-02 06:41:16.317         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.317         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.317         >>> print(''.join(results), end="")
2025-07-02 06:41:16.317         - abcDefghiJkl
2025-07-02 06:41:16.317         + abcdefGhijkl
2025-07-02 06:41:16.317         """
2025-07-02 06:41:16.317
2025-07-02 06:41:16.317         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.317         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.317         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.317         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.317         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.318
2025-07-02 06:41:16.318         # search for the pair that matches best without being identical
2025-07-02 06:41:16.318         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.318         # on junk -- unless we have to)
2025-07-02 06:41:16.318         for j in range(blo, bhi):
2025-07-02 06:41:16.318             bj = b[j]
2025-07-02 06:41:16.318             cruncher.set_seq2(bj)
2025-07-02 06:41:16.318             for i in range(alo, ahi):
2025-07-02 06:41:16.318                 ai = a[i]
2025-07-02 06:41:16.318                 if ai == bj:
2025-07-02 06:41:16.318                     if eqi is None:
2025-07-02 06:41:16.318                         eqi, eqj = i, j
2025-07-02 06:41:16.318                     continue
2025-07-02 06:41:16.318                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.318                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.318                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.318                 # compares by a factor of 3.
2025-07-02 06:41:16.318                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.319                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.319                 # of the computation is cached by cruncher
2025-07-02 06:41:16.319                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.319                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.319                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.319                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.319         if best_ratio < cutoff:
2025-07-02 06:41:16.319             # no non-identical "pretty close" pair
2025-07-02 06:41:16.319             if eqi is None:
2025-07-02 06:41:16.319                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.319                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.319                 return
2025-07-02 06:41:16.319             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.319             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.319         else:
2025-07-02 06:41:16.319             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.319             eqi = None
2025-07-02 06:41:16.319
2025-07-02 06:41:16.320         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.320         # identical
2025-07-02 06:41:16.320
2025-07-02 06:41:16.320         # pump out diffs from before the synch point
2025-07-02 06:41:16.320         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.320
2025-07-02 06:41:16.320         # do intraline marking on the synch pair
2025-07-02 06:41:16.320         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.320         if eqi is None:
2025-07-02 06:41:16.320             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.320             atags = btags = ""
2025-07-02 06:41:16.320             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.320             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.320                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.320                 if tag == 'replace':
2025-07-02 06:41:16.320                     atags += '^' * la
2025-07-02 06:41:16.320                     btags += '^' * lb
2025-07-02 06:41:16.320                 elif tag == 'delete':
2025-07-02 06:41:16.320                     atags += '-' * la
2025-07-02 06:41:16.320                 elif tag == 'insert':
2025-07-02 06:41:16.321                     btags += '+' * lb
2025-07-02 06:41:16.321                 elif tag == 'equal':
2025-07-02 06:41:16.321                     atags += ' ' * la
2025-07-02 06:41:16.321                     btags += ' ' * lb
2025-07-02 06:41:16.321                 else:
2025-07-02 06:41:16.321                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.321             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.321         else:
2025-07-02 06:41:16.321             # the synch pair is identical
2025-07-02 06:41:16.321             yield '  ' + aelt
2025-07-02 06:41:16.321
2025-07-02 06:41:16.321         # pump out diffs from after the synch point
2025-07-02 06:41:16.321 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.321
2025-07-02 06:41:16.321 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.321 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.321
2025-07-02 06:41:16.321 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.321 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.322 alo = 37, ahi = 1101
2025-07-02 06:41:16.322 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.322 blo = 37, bhi = 1101
2025-07-02 06:41:16.322
2025-07-02 06:41:16.322     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.322         g = []
2025-07-02 06:41:16.322         if alo < ahi:
2025-07-02 06:41:16.322             if blo < bhi:
2025-07-02 06:41:16.322                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.322             else:
2025-07-02 06:41:16.322                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.322         elif blo < bhi:
2025-07-02 06:41:16.322             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.322
2025-07-02 06:41:16.322 >       yield from g
2025-07-02 06:41:16.322
2025-07-02 06:41:16.322 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.322 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.322
2025-07-02 06:41:16.322 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.323 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.323 alo = 37, ahi = 1101
2025-07-02 06:41:16.323 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.323 blo = 37, bhi = 1101
2025-07-02 06:41:16.323
2025-07-02 06:41:16.323     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.323         r"""
2025-07-02 06:41:16.323         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.323         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.323         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.323         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.323
2025-07-02 06:41:16.323         Example:
2025-07-02 06:41:16.323
2025-07-02 06:41:16.323         >>> d = Differ()
2025-07-02 06:41:16.323         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.323         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.323         >>> print(''.join(results), end="")
2025-07-02 06:41:16.323         - abcDefghiJkl
2025-07-02 06:41:16.324         + abcdefGhijkl
2025-07-02 06:41:16.324         """
2025-07-02 06:41:16.324
2025-07-02 06:41:16.324         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.324         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.324         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.324         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.324         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.324
2025-07-02 06:41:16.324         # search for the pair that matches best without being identical
2025-07-02 06:41:16.324         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.324         # on junk -- unless we have to)
2025-07-02 06:41:16.324         for j in range(blo, bhi):
2025-07-02 06:41:16.324             bj = b[j]
2025-07-02 06:41:16.324             cruncher.set_seq2(bj)
2025-07-02 06:41:16.324             for i in range(alo, ahi):
2025-07-02 06:41:16.324                 ai = a[i]
2025-07-02 06:41:16.324                 if ai == bj:
2025-07-02 06:41:16.325                     if eqi is None:
2025-07-02 06:41:16.325                         eqi, eqj = i, j
2025-07-02 06:41:16.325                     continue
2025-07-02 06:41:16.325                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.325                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.325                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.325                 # compares by a factor of 3.
2025-07-02 06:41:16.325                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.325                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.325                 # of the computation is cached by cruncher
2025-07-02 06:41:16.325                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.325                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.325                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.325                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.325         if best_ratio < cutoff:
2025-07-02 06:41:16.325             # no non-identical "pretty close" pair
2025-07-02 06:41:16.325             if eqi is None:
2025-07-02 06:41:16.325                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.325                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.325                 return
2025-07-02 06:41:16.326             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.326             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.326         else:
2025-07-02 06:41:16.326             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.326             eqi = None
2025-07-02 06:41:16.326
2025-07-02 06:41:16.326         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.326         # identical
2025-07-02 06:41:16.326
2025-07-02 06:41:16.326         # pump out diffs from before the synch point
2025-07-02 06:41:16.326         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.326
2025-07-02 06:41:16.326         # do intraline marking on the synch pair
2025-07-02 06:41:16.326         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.326         if eqi is None:
2025-07-02 06:41:16.326             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.326             atags = btags = ""
2025-07-02 06:41:16.326             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.326             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.326                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.327                 if tag == 'replace':
2025-07-02 06:41:16.327                     atags += '^' * la
2025-07-02 06:41:16.327                     btags += '^' * lb
2025-07-02 06:41:16.327                 elif tag == 'delete':
2025-07-02 06:41:16.327                     atags += '-' * la
2025-07-02 06:41:16.327                 elif tag == 'insert':
2025-07-02 06:41:16.327                     btags += '+' * lb
2025-07-02 06:41:16.327                 elif tag == 'equal':
2025-07-02 06:41:16.327                     atags += ' ' * la
2025-07-02 06:41:16.327                     btags += ' ' * lb
2025-07-02 06:41:16.327                 else:
2025-07-02 06:41:16.327                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.327             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.327         else:
2025-07-02 06:41:16.327             # the synch pair is identical
2025-07-02 06:41:16.327             yield '  ' + aelt
2025-07-02 06:41:16.327
2025-07-02 06:41:16.327         # pump out diffs from after the synch point
2025-07-02 06:41:16.327 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.328
2025-07-02 06:41:16.328 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.328 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.328
2025-07-02 06:41:16.328 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.328 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.328 alo = 38, ahi = 1101
2025-07-02 06:41:16.328 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.328 blo = 38, bhi = 1101
2025-07-02 06:41:16.328
2025-07-02 06:41:16.328     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.328         g = []
2025-07-02 06:41:16.328         if alo < ahi:
2025-07-02 06:41:16.328             if blo < bhi:
2025-07-02 06:41:16.328                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.328             else:
2025-07-02 06:41:16.328                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.328         elif blo < bhi:
2025-07-02 06:41:16.329             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.329
2025-07-02 06:41:16.329 >       yield from g
2025-07-02 06:41:16.329
2025-07-02 06:41:16.329 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.329 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.329
2025-07-02 06:41:16.329 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.329 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.329 alo = 38, ahi = 1101
2025-07-02 06:41:16.329 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.329 blo = 38, bhi = 1101
2025-07-02 06:41:16.329
2025-07-02 06:41:16.329     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.329         r"""
2025-07-02 06:41:16.329         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.329         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.329         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.329         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.330
2025-07-02 06:41:16.330         Example:
2025-07-02 06:41:16.330
2025-07-02 06:41:16.330         >>> d = Differ()
2025-07-02 06:41:16.330         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.330         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.330         >>> print(''.join(results), end="")
2025-07-02 06:41:16.330         - abcDefghiJkl
2025-07-02 06:41:16.330         + abcdefGhijkl
2025-07-02 06:41:16.330         """
2025-07-02 06:41:16.330
2025-07-02 06:41:16.330         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.330         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.330         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.330         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.330         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.330
2025-07-02 06:41:16.330         # search for the pair that matches best without being identical
2025-07-02 06:41:16.331         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.331         # on junk -- unless we have to)
2025-07-02 06:41:16.331         for j in range(blo, bhi):
2025-07-02 06:41:16.331             bj = b[j]
2025-07-02 06:41:16.331             cruncher.set_seq2(bj)
2025-07-02 06:41:16.331             for i in range(alo, ahi):
2025-07-02 06:41:16.331                 ai = a[i]
2025-07-02 06:41:16.331                 if ai == bj:
2025-07-02 06:41:16.331                     if eqi is None:
2025-07-02 06:41:16.331                         eqi, eqj = i, j
2025-07-02 06:41:16.331                     continue
2025-07-02 06:41:16.331                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.331                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.331                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.331                 # compares by a factor of 3.
2025-07-02 06:41:16.331                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.331                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.331                 # of the computation is cached by cruncher
2025-07-02 06:41:16.331                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.331                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.331                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.332                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.332         if best_ratio < cutoff:
2025-07-02 06:41:16.332             # no non-identical "pretty close" pair
2025-07-02 06:41:16.332             if eqi is None:
2025-07-02 06:41:16.332                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.332                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.332                 return
2025-07-02 06:41:16.332             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.332             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.332         else:
2025-07-02 06:41:16.332             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.332             eqi = None
2025-07-02 06:41:16.332
2025-07-02 06:41:16.332         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.332         # identical
2025-07-02 06:41:16.332
2025-07-02 06:41:16.332         # pump out diffs from before the synch point
2025-07-02 06:41:16.332         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.332
2025-07-02 06:41:16.332         # do intraline marking on the synch pair
2025-07-02 06:41:16.333         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.333         if eqi is None:
2025-07-02 06:41:16.333             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.333             atags = btags = ""
2025-07-02 06:41:16.333             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.333             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.333                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.333                 if tag == 'replace':
2025-07-02 06:41:16.333                     atags += '^' * la
2025-07-02 06:41:16.333                     btags += '^' * lb
2025-07-02 06:41:16.333                 elif tag == 'delete':
2025-07-02 06:41:16.333                     atags += '-' * la
2025-07-02 06:41:16.333                 elif tag == 'insert':
2025-07-02 06:41:16.333                     btags += '+' * lb
2025-07-02 06:41:16.333                 elif tag == 'equal':
2025-07-02 06:41:16.333                     atags += ' ' * la
2025-07-02 06:41:16.333                     btags += ' ' * lb
2025-07-02 06:41:16.333                 else:
2025-07-02 06:41:16.333                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.333             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.333         else:
2025-07-02 06:41:16.334             # the synch pair is identical
2025-07-02 06:41:16.334             yield '  ' + aelt
2025-07-02 06:41:16.334
2025-07-02 06:41:16.334         # pump out diffs from after the synch point
2025-07-02 06:41:16.334 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.334
2025-07-02 06:41:16.334 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.334 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.334
2025-07-02 06:41:16.334 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.334 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.334 alo = 39, ahi = 1101
2025-07-02 06:41:16.334 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.334 blo = 39, bhi = 1101
2025-07-02 06:41:16.334
2025-07-02 06:41:16.334     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.334         g = []
2025-07-02 06:41:16.334         if alo < ahi:
2025-07-02 06:41:16.335             if blo < bhi:
2025-07-02 06:41:16.335                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.335             else:
2025-07-02 06:41:16.335                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.335         elif blo < bhi:
2025-07-02 06:41:16.335             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.335
2025-07-02 06:41:16.335 >       yield from g
2025-07-02 06:41:16.335
2025-07-02 06:41:16.335 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.335 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.335
2025-07-02 06:41:16.335 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.335 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.335 alo = 39, ahi = 1101
2025-07-02 06:41:16.335 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.335 blo = 39, bhi = 1101
2025-07-02 06:41:16.335
2025-07-02 06:41:16.335     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.335         r"""
2025-07-02 06:41:16.336         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.336         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.336         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.336         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.336
2025-07-02 06:41:16.336         Example:
2025-07-02 06:41:16.336
2025-07-02 06:41:16.336         >>> d = Differ()
2025-07-02 06:41:16.336         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.336         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.336         >>> print(''.join(results), end="")
2025-07-02 06:41:16.336         - abcDefghiJkl
2025-07-02 06:41:16.336         + abcdefGhijkl
2025-07-02 06:41:16.336         """
2025-07-02 06:41:16.336
2025-07-02 06:41:16.337         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.337         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.337         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.337         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.337         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.337
2025-07-02 06:41:16.337         # search for the pair that matches best without being identical
2025-07-02 06:41:16.337         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.337         # on junk -- unless we have to)
2025-07-02 06:41:16.337         for j in range(blo, bhi):
2025-07-02 06:41:16.337             bj = b[j]
2025-07-02 06:41:16.337             cruncher.set_seq2(bj)
2025-07-02 06:41:16.337             for i in range(alo, ahi):
2025-07-02 06:41:16.337                 ai = a[i]
2025-07-02 06:41:16.337                 if ai == bj:
2025-07-02 06:41:16.337                     if eqi is None:
2025-07-02 06:41:16.337                         eqi, eqj = i, j
2025-07-02 06:41:16.337                     continue
2025-07-02 06:41:16.337                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.338                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.338                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.338                 # compares by a factor of 3.
2025-07-02 06:41:16.338                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.338                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.338                 # of the computation is cached by cruncher
2025-07-02 06:41:16.338                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.338                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.338                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.338                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.338         if best_ratio < cutoff:
2025-07-02 06:41:16.338             # no non-identical "pretty close" pair
2025-07-02 06:41:16.338             if eqi is None:
2025-07-02 06:41:16.338                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.338                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.338                 return
2025-07-02 06:41:16.338             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.338             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.338         else:
2025-07-02 06:41:16.338             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.338             eqi = None
2025-07-02 06:41:16.339
2025-07-02 06:41:16.339         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.339         # identical
2025-07-02 06:41:16.339
2025-07-02 06:41:16.339         # pump out diffs from before the synch point
2025-07-02 06:41:16.339         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.339
2025-07-02 06:41:16.339         # do intraline marking on the synch pair
2025-07-02 06:41:16.339         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.339         if eqi is None:
2025-07-02 06:41:16.339             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.339             atags = btags = ""
2025-07-02 06:41:16.339             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.339             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.339                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.339                 if tag == 'replace':
2025-07-02 06:41:16.339                     atags += '^' * la
2025-07-02 06:41:16.339                     btags += '^' * lb
2025-07-02 06:41:16.339                 elif tag == 'delete':
2025-07-02 06:41:16.339                     atags += '-' * la
2025-07-02 06:41:16.340                 elif tag == 'insert':
2025-07-02 06:41:16.340                     btags += '+' * lb
2025-07-02 06:41:16.340                 elif tag == 'equal':
2025-07-02 06:41:16.340                     atags += ' ' * la
2025-07-02 06:41:16.340                     btags += ' ' * lb
2025-07-02 06:41:16.340                 else:
2025-07-02 06:41:16.340                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.340             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.340         else:
2025-07-02 06:41:16.340             # the synch pair is identical
2025-07-02 06:41:16.340             yield '  ' + aelt
2025-07-02 06:41:16.340
2025-07-02 06:41:16.340         # pump out diffs from after the synch point
2025-07-02 06:41:16.340 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.340
2025-07-02 06:41:16.340 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.340 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.340
2025-07-02 06:41:16.340 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.340 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.341 alo = 40, ahi = 1101
2025-07-02 06:41:16.341 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.341 blo = 40, bhi = 1101
2025-07-02 06:41:16.341
2025-07-02 06:41:16.341     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.341         g = []
2025-07-02 06:41:16.341         if alo < ahi:
2025-07-02 06:41:16.341             if blo < bhi:
2025-07-02 06:41:16.341                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.341             else:
2025-07-02 06:41:16.341                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.341         elif blo < bhi:
2025-07-02 06:41:16.341             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.341
2025-07-02 06:41:16.341 >       yield from g
2025-07-02 06:41:16.341
2025-07-02 06:41:16.341 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.341 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.341
2025-07-02 06:41:16.341 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.341 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.342 alo = 40, ahi = 1101
2025-07-02 06:41:16.342 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.342 blo = 40, bhi = 1101
2025-07-02 06:41:16.342
2025-07-02 06:41:16.342     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.342         r"""
2025-07-02 06:41:16.342         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.342         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.342         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.342         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.342
2025-07-02 06:41:16.342         Example:
2025-07-02 06:41:16.342
2025-07-02 06:41:16.342         >>> d = Differ()
2025-07-02 06:41:16.342         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.342         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.342         >>> print(''.join(results), end="")
2025-07-02 06:41:16.342         - abcDefghiJkl
2025-07-02 06:41:16.342         + abcdefGhijkl
2025-07-02 06:41:16.343         """
2025-07-02 06:41:16.343
2025-07-02 06:41:16.343         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.343         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.343         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.343         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.343         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.343
2025-07-02 06:41:16.343         # search for the pair that matches best without being identical
2025-07-02 06:41:16.343         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.343         # on junk -- unless we have to)
2025-07-02 06:41:16.343         for j in range(blo, bhi):
2025-07-02 06:41:16.343             bj = b[j]
2025-07-02 06:41:16.343             cruncher.set_seq2(bj)
2025-07-02 06:41:16.343             for i in range(alo, ahi):
2025-07-02 06:41:16.343                 ai = a[i]
2025-07-02 06:41:16.343                 if ai == bj:
2025-07-02 06:41:16.343                     if eqi is None:
2025-07-02 06:41:16.343                         eqi, eqj = i, j
2025-07-02 06:41:16.344                     continue
2025-07-02 06:41:16.344                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.344                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.344                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.344                 # compares by a factor of 3.
2025-07-02 06:41:16.344                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.344                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.344                 # of the computation is cached by cruncher
2025-07-02 06:41:16.344                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.344                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.344                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.344                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.344         if best_ratio < cutoff:
2025-07-02 06:41:16.344             # no non-identical "pretty close" pair
2025-07-02 06:41:16.344             if eqi is None:
2025-07-02 06:41:16.344                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.344                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.344                 return
2025-07-02 06:41:16.345             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.345             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.345         else:
2025-07-02 06:41:16.345             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.345             eqi = None
2025-07-02 06:41:16.345
2025-07-02 06:41:16.345         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.345         # identical
2025-07-02 06:41:16.345
2025-07-02 06:41:16.345         # pump out diffs from before the synch point
2025-07-02 06:41:16.345         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.345
2025-07-02 06:41:16.345         # do intraline marking on the synch pair
2025-07-02 06:41:16.345         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.345         if eqi is None:
2025-07-02 06:41:16.345             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.345             atags = btags = ""
2025-07-02 06:41:16.345             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.345             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.345                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.346                 if tag == 'replace':
2025-07-02 06:41:16.346                     atags += '^' * la
2025-07-02 06:41:16.346                     btags += '^' * lb
2025-07-02 06:41:16.346                 elif tag == 'delete':
2025-07-02 06:41:16.346                     atags += '-' * la
2025-07-02 06:41:16.346                 elif tag == 'insert':
2025-07-02 06:41:16.346                     btags += '+' * lb
2025-07-02 06:41:16.346                 elif tag == 'equal':
2025-07-02 06:41:16.346                     atags += ' ' * la
2025-07-02 06:41:16.346                     btags += ' ' * lb
2025-07-02 06:41:16.346                 else:
2025-07-02 06:41:16.346                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.346             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.346         else:
2025-07-02 06:41:16.346             # the synch pair is identical
2025-07-02 06:41:16.346             yield '  ' + aelt
2025-07-02 06:41:16.346
2025-07-02 06:41:16.346         # pump out diffs from after the synch point
2025-07-02 06:41:16.346 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.346
2025-07-02 06:41:16.347 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.347 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.347
2025-07-02 06:41:16.347 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.347 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.347 alo = 41, ahi = 1101
2025-07-02 06:41:16.347 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.347 blo = 41, bhi = 1101
2025-07-02 06:41:16.347
2025-07-02 06:41:16.347     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.347         g = []
2025-07-02 06:41:16.347         if alo < ahi:
2025-07-02 06:41:16.347             if blo < bhi:
2025-07-02 06:41:16.347                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.347             else:
2025-07-02 06:41:16.347                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.347         elif blo < bhi:
2025-07-02 06:41:16.347             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.347
2025-07-02 06:41:16.347 >       yield from g
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.348 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.348 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.348 alo = 41, ahi = 1101
2025-07-02 06:41:16.348 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.348 blo = 41, bhi = 1101
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.348         r"""
2025-07-02 06:41:16.348         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.348         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.348         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.348         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348         Example:
2025-07-02 06:41:16.348
2025-07-02 06:41:16.348         >>> d = Differ()
2025-07-02 06:41:16.349         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.349         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.349         >>> print(''.join(results), end="")
2025-07-02 06:41:16.349         - abcDefghiJkl
2025-07-02 06:41:16.349         + abcdefGhijkl
2025-07-02 06:41:16.349         """
2025-07-02 06:41:16.349
2025-07-02 06:41:16.349         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.349         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.349         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.349         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.349         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.349
2025-07-02 06:41:16.349         # search for the pair that matches best without being identical
2025-07-02 06:41:16.349         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.349         # on junk -- unless we have to)
2025-07-02 06:41:16.349         for j in range(blo, bhi):
2025-07-02 06:41:16.349             bj = b[j]
2025-07-02 06:41:16.350             cruncher.set_seq2(bj)
2025-07-02 06:41:16.350             for i in range(alo, ahi):
2025-07-02 06:41:16.350                 ai = a[i]
2025-07-02 06:41:16.350                 if ai == bj:
2025-07-02 06:41:16.350                     if eqi is None:
2025-07-02 06:41:16.350                         eqi, eqj = i, j
2025-07-02 06:41:16.350                     continue
2025-07-02 06:41:16.350                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.350                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.350                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.350                 # compares by a factor of 3.
2025-07-02 06:41:16.350                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.350                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.350                 # of the computation is cached by cruncher
2025-07-02 06:41:16.350                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.350                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.350                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.350                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.351         if best_ratio < cutoff:
2025-07-02 06:41:16.351             # no non-identical "pretty close" pair
2025-07-02 06:41:16.351             if eqi is None:
2025-07-02 06:41:16.351                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.351                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.351                 return
2025-07-02 06:41:16.351             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.351             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.351         else:
2025-07-02 06:41:16.351             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.351             eqi = None
2025-07-02 06:41:16.351
2025-07-02 06:41:16.351         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.351         # identical
2025-07-02 06:41:16.351
2025-07-02 06:41:16.351         # pump out diffs from before the synch point
2025-07-02 06:41:16.351         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.351
2025-07-02 06:41:16.351         # do intraline marking on the synch pair
2025-07-02 06:41:16.352         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.352         if eqi is None:
2025-07-02 06:41:16.352             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.352             atags = btags = ""
2025-07-02 06:41:16.352             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.352             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.352                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.352                 if tag == 'replace':
2025-07-02 06:41:16.352                     atags += '^' * la
2025-07-02 06:41:16.352                     btags += '^' * lb
2025-07-02 06:41:16.352                 elif tag == 'delete':
2025-07-02 06:41:16.352                     atags += '-' * la
2025-07-02 06:41:16.352                 elif tag == 'insert':
2025-07-02 06:41:16.352                     btags += '+' * lb
2025-07-02 06:41:16.352                 elif tag == 'equal':
2025-07-02 06:41:16.352                     atags += ' ' * la
2025-07-02 06:41:16.352                     btags += ' ' * lb
2025-07-02 06:41:16.352                 else:
2025-07-02 06:41:16.352                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.353             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.353         else:
2025-07-02 06:41:16.353             # the synch pair is identical
2025-07-02 06:41:16.353             yield '  ' + aelt
2025-07-02 06:41:16.353
2025-07-02 06:41:16.353         # pump out diffs from after the synch point
2025-07-02 06:41:16.353 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.353
2025-07-02 06:41:16.353 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.353 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.353
2025-07-02 06:41:16.353 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.353 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.353 alo = 42, ahi = 1101
2025-07-02 06:41:16.353 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.353 blo = 42, bhi = 1101
2025-07-02 06:41:16.353
2025-07-02 06:41:16.353     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.354         g = []
2025-07-02 06:41:16.354         if alo < ahi:
2025-07-02 06:41:16.354             if blo < bhi:
2025-07-02 06:41:16.354                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.354             else:
2025-07-02 06:41:16.354                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.354         elif blo < bhi:
2025-07-02 06:41:16.354             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.354
2025-07-02 06:41:16.354 >       yield from g
2025-07-02 06:41:16.354
2025-07-02 06:41:16.354 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.354 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.354
2025-07-02 06:41:16.354 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.354 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.354 alo = 42, ahi = 1101
2025-07-02 06:41:16.354 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.354 blo = 42, bhi = 1101
2025-07-02 06:41:16.355
2025-07-02 06:41:16.355     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.355         r"""
2025-07-02 06:41:16.355         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.355         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.355         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.355         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.355
2025-07-02 06:41:16.355         Example:
2025-07-02 06:41:16.355
2025-07-02 06:41:16.355         >>> d = Differ()
2025-07-02 06:41:16.355         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.355         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.355         >>> print(''.join(results), end="")
2025-07-02 06:41:16.355         - abcDefghiJkl
2025-07-02 06:41:16.355         + abcdefGhijkl
2025-07-02 06:41:16.355         """
2025-07-02 06:41:16.355
2025-07-02 06:41:16.356         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.356         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.356         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.356         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.356         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.356
2025-07-02 06:41:16.356         # search for the pair that matches best without being identical
2025-07-02 06:41:16.356         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.356         # on junk -- unless we have to)
2025-07-02 06:41:16.356         for j in range(blo, bhi):
2025-07-02 06:41:16.356             bj = b[j]
2025-07-02 06:41:16.356             cruncher.set_seq2(bj)
2025-07-02 06:41:16.356             for i in range(alo, ahi):
2025-07-02 06:41:16.356                 ai = a[i]
2025-07-02 06:41:16.356                 if ai == bj:
2025-07-02 06:41:16.356                     if eqi is None:
2025-07-02 06:41:16.356                         eqi, eqj = i, j
2025-07-02 06:41:16.356                     continue
2025-07-02 06:41:16.356                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.356                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.356                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.357                 # compares by a factor of 3.
2025-07-02 06:41:16.357                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.357                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.357                 # of the computation is cached by cruncher
2025-07-02 06:41:16.357                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.357                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.357                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.357                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.357         if best_ratio < cutoff:
2025-07-02 06:41:16.357             # no non-identical "pretty close" pair
2025-07-02 06:41:16.357             if eqi is None:
2025-07-02 06:41:16.357                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.357                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.357                 return
2025-07-02 06:41:16.357             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.357             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.357         else:
2025-07-02 06:41:16.357             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.357             eqi = None
2025-07-02 06:41:16.357
2025-07-02 06:41:16.358         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.358         # identical
2025-07-02 06:41:16.358
2025-07-02 06:41:16.358         # pump out diffs from before the synch point
2025-07-02 06:41:16.358         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.358
2025-07-02 06:41:16.358         # do intraline marking on the synch pair
2025-07-02 06:41:16.358         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.358         if eqi is None:
2025-07-02 06:41:16.358             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.358             atags = btags = ""
2025-07-02 06:41:16.358             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.358             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.358                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.358                 if tag == 'replace':
2025-07-02 06:41:16.358                     atags += '^' * la
2025-07-02 06:41:16.358                     btags += '^' * lb
2025-07-02 06:41:16.358                 elif tag == 'delete':
2025-07-02 06:41:16.358                     atags += '-' * la
2025-07-02 06:41:16.358                 elif tag == 'insert':
2025-07-02 06:41:16.359                     btags += '+' * lb
2025-07-02 06:41:16.359                 elif tag == 'equal':
2025-07-02 06:41:16.359                     atags += ' ' * la
2025-07-02 06:41:16.359                     btags += ' ' * lb
2025-07-02 06:41:16.359                 else:
2025-07-02 06:41:16.359                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.359             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.359         else:
2025-07-02 06:41:16.359             # the synch pair is identical
2025-07-02 06:41:16.359             yield '  ' + aelt
2025-07-02 06:41:16.359
2025-07-02 06:41:16.359         # pump out diffs from after the synch point
2025-07-02 06:41:16.359 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.359
2025-07-02 06:41:16.359 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.359 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.359
2025-07-02 06:41:16.359 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.359 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.359 alo = 43, ahi = 1101
2025-07-02 06:41:16.359 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.360 blo = 43, bhi = 1101
2025-07-02 06:41:16.360
2025-07-02 06:41:16.360     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.360         g = []
2025-07-02 06:41:16.360         if alo < ahi:
2025-07-02 06:41:16.360             if blo < bhi:
2025-07-02 06:41:16.360                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.360             else:
2025-07-02 06:41:16.360                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.360         elif blo < bhi:
2025-07-02 06:41:16.360             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.360
2025-07-02 06:41:16.360 >       yield from g
2025-07-02 06:41:16.360
2025-07-02 06:41:16.360 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.360 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.360
2025-07-02 06:41:16.360 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.360 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.360 alo = 43, ahi = 1101
2025-07-02 06:41:16.361 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.361 blo = 43, bhi = 1101
2025-07-02 06:41:16.361
2025-07-02 06:41:16.361     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.361         r"""
2025-07-02 06:41:16.361         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.361         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.361         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.361         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.361
2025-07-02 06:41:16.361         Example:
2025-07-02 06:41:16.361
2025-07-02 06:41:16.361         >>> d = Differ()
2025-07-02 06:41:16.361         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.361         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.361         >>> print(''.join(results), end="")
2025-07-02 06:41:16.361         - abcDefghiJkl
2025-07-02 06:41:16.361         + abcdefGhijkl
2025-07-02 06:41:16.362         """
2025-07-02 06:41:16.362
2025-07-02 06:41:16.362         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.362         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.362         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.362         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.362         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.362
2025-07-02 06:41:16.362         # search for the pair that matches best without being identical
2025-07-02 06:41:16.362         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.362         # on junk -- unless we have to)
2025-07-02 06:41:16.362         for j in range(blo, bhi):
2025-07-02 06:41:16.362             bj = b[j]
2025-07-02 06:41:16.362             cruncher.set_seq2(bj)
2025-07-02 06:41:16.362             for i in range(alo, ahi):
2025-07-02 06:41:16.362                 ai = a[i]
2025-07-02 06:41:16.362                 if ai == bj:
2025-07-02 06:41:16.362                     if eqi is None:
2025-07-02 06:41:16.362                         eqi, eqj = i, j
2025-07-02 06:41:16.363                     continue
2025-07-02 06:41:16.363                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.363                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.363                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.363                 # compares by a factor of 3.
2025-07-02 06:41:16.363                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.363                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.363                 # of the computation is cached by cruncher
2025-07-02 06:41:16.363                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.363                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.363                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.363                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.363         if best_ratio < cutoff:
2025-07-02 06:41:16.363             # no non-identical "pretty close" pair
2025-07-02 06:41:16.363             if eqi is None:
2025-07-02 06:41:16.363                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.363                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.363                 return
2025-07-02 06:41:16.363             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.364             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.364         else:
2025-07-02 06:41:16.364             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.364             eqi = None
2025-07-02 06:41:16.364
2025-07-02 06:41:16.364         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.364         # identical
2025-07-02 06:41:16.364
2025-07-02 06:41:16.364         # pump out diffs from before the synch point
2025-07-02 06:41:16.364         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.364
2025-07-02 06:41:16.364         # do intraline marking on the synch pair
2025-07-02 06:41:16.364         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.364         if eqi is None:
2025-07-02 06:41:16.364             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.364             atags = btags = ""
2025-07-02 06:41:16.364             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.364             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.364                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.364                 if tag == 'replace':
2025-07-02 06:41:16.365                     atags += '^' * la
2025-07-02 06:41:16.365                     btags += '^' * lb
2025-07-02 06:41:16.365                 elif tag == 'delete':
2025-07-02 06:41:16.365                     atags += '-' * la
2025-07-02 06:41:16.365                 elif tag == 'insert':
2025-07-02 06:41:16.365                     btags += '+' * lb
2025-07-02 06:41:16.365                 elif tag == 'equal':
2025-07-02 06:41:16.365                     atags += ' ' * la
2025-07-02 06:41:16.365                     btags += ' ' * lb
2025-07-02 06:41:16.365                 else:
2025-07-02 06:41:16.365                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.365             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.365         else:
2025-07-02 06:41:16.365             # the synch pair is identical
2025-07-02 06:41:16.365             yield '  ' + aelt
2025-07-02 06:41:16.365
2025-07-02 06:41:16.365         # pump out diffs from after the synch point
2025-07-02 06:41:16.365 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.365
2025-07-02 06:41:16.365 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.365 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.366
2025-07-02 06:41:16.366 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.366 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.366 alo = 44, ahi = 1101
2025-07-02 06:41:16.366 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.366 blo = 44, bhi = 1101
2025-07-02 06:41:16.366
2025-07-02 06:41:16.366     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.366         g = []
2025-07-02 06:41:16.366         if alo < ahi:
2025-07-02 06:41:16.366             if blo < bhi:
2025-07-02 06:41:16.366                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.366             else:
2025-07-02 06:41:16.366                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.366         elif blo < bhi:
2025-07-02 06:41:16.366             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.366
2025-07-02 06:41:16.367 >       yield from g
2025-07-02 06:41:16.367
2025-07-02 06:41:16.367 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.367 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.367
2025-07-02 06:41:16.367 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.367 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.367 alo = 44, ahi = 1101
2025-07-02 06:41:16.367 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.367 blo = 44, bhi = 1101
2025-07-02 06:41:16.367
2025-07-02 06:41:16.367     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.367         r"""
2025-07-02 06:41:16.367         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.367         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.367         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.367         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.367
2025-07-02 06:41:16.367         Example:
2025-07-02 06:41:16.368
2025-07-02 06:41:16.368         >>> d = Differ()
2025-07-02 06:41:16.368         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.368         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.368         >>> print(''.join(results), end="")
2025-07-02 06:41:16.368         - abcDefghiJkl
2025-07-02 06:41:16.368         + abcdefGhijkl
2025-07-02 06:41:16.368         """
2025-07-02 06:41:16.368
2025-07-02 06:41:16.368         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.368         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.368         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.368         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.368         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.368
2025-07-02 06:41:16.368         # search for the pair that matches best without being identical
2025-07-02 06:41:16.368         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.368         # on junk -- unless we have to)
2025-07-02 06:41:16.369         for j in range(blo, bhi):
2025-07-02 06:41:16.369             bj = b[j]
2025-07-02 06:41:16.369             cruncher.set_seq2(bj)
2025-07-02 06:41:16.369             for i in range(alo, ahi):
2025-07-02 06:41:16.369                 ai = a[i]
2025-07-02 06:41:16.369                 if ai == bj:
2025-07-02 06:41:16.369                     if eqi is None:
2025-07-02 06:41:16.369                         eqi, eqj = i, j
2025-07-02 06:41:16.369                     continue
2025-07-02 06:41:16.369                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.369                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.369                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.369                 # compares by a factor of 3.
2025-07-02 06:41:16.369                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.369                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.369                 # of the computation is cached by cruncher
2025-07-02 06:41:16.369                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.369                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.369                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.369                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.370         if best_ratio < cutoff:
2025-07-02 06:41:16.370             # no non-identical "pretty close" pair
2025-07-02 06:41:16.370             if eqi is None:
2025-07-02 06:41:16.370                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.370                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.370                 return
2025-07-02 06:41:16.370             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.370             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.370         else:
2025-07-02 06:41:16.370             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.370             eqi = None
2025-07-02 06:41:16.370
2025-07-02 06:41:16.370         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.370         # identical
2025-07-02 06:41:16.370
2025-07-02 06:41:16.370         # pump out diffs from before the synch point
2025-07-02 06:41:16.370         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.370
2025-07-02 06:41:16.370         # do intraline marking on the synch pair
2025-07-02 06:41:16.370         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.371         if eqi is None:
2025-07-02 06:41:16.371             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.371             atags = btags = ""
2025-07-02 06:41:16.371             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.371             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.371                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.371                 if tag == 'replace':
2025-07-02 06:41:16.371                     atags += '^' * la
2025-07-02 06:41:16.371                     btags += '^' * lb
2025-07-02 06:41:16.371                 elif tag == 'delete':
2025-07-02 06:41:16.371                     atags += '-' * la
2025-07-02 06:41:16.371                 elif tag == 'insert':
2025-07-02 06:41:16.371                     btags += '+' * lb
2025-07-02 06:41:16.371                 elif tag == 'equal':
2025-07-02 06:41:16.371                     atags += ' ' * la
2025-07-02 06:41:16.371                     btags += ' ' * lb
2025-07-02 06:41:16.371                 else:
2025-07-02 06:41:16.371                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.372             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.372         else:
2025-07-02 06:41:16.372             # the synch pair is identical
2025-07-02 06:41:16.372             yield '  ' + aelt
2025-07-02 06:41:16.372
2025-07-02 06:41:16.372         # pump out diffs from after the synch point
2025-07-02 06:41:16.372 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.372
2025-07-02 06:41:16.372 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.372 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.372
2025-07-02 06:41:16.372 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.372 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.372 alo = 45, ahi = 1101
2025-07-02 06:41:16.372 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.372 blo = 45, bhi = 1101
2025-07-02 06:41:16.372
2025-07-02 06:41:16.372     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.372         g = []
2025-07-02 06:41:16.372         if alo < ahi:
2025-07-02 06:41:16.373             if blo < bhi:
2025-07-02 06:41:16.373                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.373             else:
2025-07-02 06:41:16.373                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.373         elif blo < bhi:
2025-07-02 06:41:16.373             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.373
2025-07-02 06:41:16.373 >       yield from g
2025-07-02 06:41:16.373
2025-07-02 06:41:16.373 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.373 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.373
2025-07-02 06:41:16.373 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.373 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.373 alo = 45, ahi = 1101
2025-07-02 06:41:16.373 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.373 blo = 45, bhi = 1101
2025-07-02 06:41:16.373
2025-07-02 06:41:16.373     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.374         r"""
2025-07-02 06:41:16.374         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.374         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.374         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.374         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.374
2025-07-02 06:41:16.374         Example:
2025-07-02 06:41:16.374
2025-07-02 06:41:16.374         >>> d = Differ()
2025-07-02 06:41:16.374         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.374         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.374         >>> print(''.join(results), end="")
2025-07-02 06:41:16.374         - abcDefghiJkl
2025-07-02 06:41:16.374         + abcdefGhijkl
2025-07-02 06:41:16.374         """
2025-07-02 06:41:16.374
2025-07-02 06:41:16.374         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.374         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.375         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.375         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.375         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.375
2025-07-02 06:41:16.375         # search for the pair that matches best without being identical
2025-07-02 06:41:16.375         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.375         # on junk -- unless we have to)
2025-07-02 06:41:16.375         for j in range(blo, bhi):
2025-07-02 06:41:16.375             bj = b[j]
2025-07-02 06:41:16.375             cruncher.set_seq2(bj)
2025-07-02 06:41:16.375             for i in range(alo, ahi):
2025-07-02 06:41:16.375                 ai = a[i]
2025-07-02 06:41:16.375                 if ai == bj:
2025-07-02 06:41:16.375                     if eqi is None:
2025-07-02 06:41:16.375                         eqi, eqj = i, j
2025-07-02 06:41:16.375                     continue
2025-07-02 06:41:16.375                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.375                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.375                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.375                 # compares by a factor of 3.
2025-07-02 06:41:16.375                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.376                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.376                 # of the computation is cached by cruncher
2025-07-02 06:41:16.376                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.376                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.376                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.376                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.376         if best_ratio < cutoff:
2025-07-02 06:41:16.376             # no non-identical "pretty close" pair
2025-07-02 06:41:16.376             if eqi is None:
2025-07-02 06:41:16.376                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.376                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.376                 return
2025-07-02 06:41:16.376             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.376             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.376         else:
2025-07-02 06:41:16.376             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.376             eqi = None
2025-07-02 06:41:16.376
2025-07-02 06:41:16.376         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.376         # identical
2025-07-02 06:41:16.377
2025-07-02 06:41:16.377         # pump out diffs from before the synch point
2025-07-02 06:41:16.377         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.377
2025-07-02 06:41:16.377         # do intraline marking on the synch pair
2025-07-02 06:41:16.377         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.377         if eqi is None:
2025-07-02 06:41:16.377             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.377             atags = btags = ""
2025-07-02 06:41:16.377             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.377             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.377                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.377                 if tag == 'replace':
2025-07-02 06:41:16.377                     atags += '^' * la
2025-07-02 06:41:16.377                     btags += '^' * lb
2025-07-02 06:41:16.377                 elif tag == 'delete':
2025-07-02 06:41:16.377                     atags += '-' * la
2025-07-02 06:41:16.377                 elif tag == 'insert':
2025-07-02 06:41:16.377                     btags += '+' * lb
2025-07-02 06:41:16.377                 elif tag == 'equal':
2025-07-02 06:41:16.377                     atags += ' ' * la
2025-07-02 06:41:16.378                     btags += ' ' * lb
2025-07-02 06:41:16.378                 else:
2025-07-02 06:41:16.378                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.378             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.378         else:
2025-07-02 06:41:16.378             # the synch pair is identical
2025-07-02 06:41:16.378             yield '  ' + aelt
2025-07-02 06:41:16.378
2025-07-02 06:41:16.378         # pump out diffs from after the synch point
2025-07-02 06:41:16.378 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.378
2025-07-02 06:41:16.378 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.378 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.378
2025-07-02 06:41:16.378 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.378 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.378 alo = 48, ahi = 1101
2025-07-02 06:41:16.378 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.378 blo = 48, bhi = 1101
2025-07-02 06:41:16.378
2025-07-02 06:41:16.379     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.379         g = []
2025-07-02 06:41:16.379         if alo < ahi:
2025-07-02 06:41:16.379             if blo < bhi:
2025-07-02 06:41:16.379                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.379             else:
2025-07-02 06:41:16.379                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.379         elif blo < bhi:
2025-07-02 06:41:16.379             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 >       yield from g
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.379 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.379 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.379 alo = 48, ahi = 1101
2025-07-02 06:41:16.379 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.379 blo = 48, bhi = 1101
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.379         r"""
2025-07-02 06:41:16.379         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.379         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.379         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.379         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379         Example:
2025-07-02 06:41:16.379
2025-07-02 06:41:16.379         >>> d = Differ()
2025-07-02 06:41:16.379         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.380         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.380         >>> print(''.join(results), end="")
2025-07-02 06:41:16.380         - abcDefghiJkl
2025-07-02 06:41:16.380         + abcdefGhijkl
2025-07-02 06:41:16.380         """
2025-07-02 06:41:16.380
2025-07-02 06:41:16.380         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.380         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.380         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.380         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.380         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.380
2025-07-02 06:41:16.380         # search for the pair that matches best without being identical
2025-07-02 06:41:16.380         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.380         # on junk -- unless we have to)
2025-07-02 06:41:16.380         for j in range(blo, bhi):
2025-07-02 06:41:16.380             bj = b[j]
2025-07-02 06:41:16.381             cruncher.set_seq2(bj)
2025-07-02 06:41:16.381             for i in range(alo, ahi):
2025-07-02 06:41:16.381                 ai = a[i]
2025-07-02 06:41:16.381                 if ai == bj:
2025-07-02 06:41:16.381                     if eqi is None:
2025-07-02 06:41:16.381                         eqi, eqj = i, j
2025-07-02 06:41:16.381                     continue
2025-07-02 06:41:16.381                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.381                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.381                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.381                 # compares by a factor of 3.
2025-07-02 06:41:16.381                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.381                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.381                 # of the computation is cached by cruncher
2025-07-02 06:41:16.381                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.381                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.381                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.381                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.382         if best_ratio < cutoff:
2025-07-02 06:41:16.382             # no non-identical "pretty close" pair
2025-07-02 06:41:16.382             if eqi is None:
2025-07-02 06:41:16.382                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.382                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.382                 return
2025-07-02 06:41:16.382             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.382             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.382         else:
2025-07-02 06:41:16.382             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.382             eqi = None
2025-07-02 06:41:16.382
2025-07-02 06:41:16.382         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.382         # identical
2025-07-02 06:41:16.382
2025-07-02 06:41:16.382         # pump out diffs from before the synch point
2025-07-02 06:41:16.382         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.382
2025-07-02 06:41:16.382         # do intraline marking on the synch pair
2025-07-02 06:41:16.382         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.382         if eqi is None:
2025-07-02 06:41:16.383             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.383             atags = btags = ""
2025-07-02 06:41:16.383             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.383             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.383                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.383                 if tag == 'replace':
2025-07-02 06:41:16.383                     atags += '^' * la
2025-07-02 06:41:16.383                     btags += '^' * lb
2025-07-02 06:41:16.383                 elif tag == 'delete':
2025-07-02 06:41:16.383                     atags += '-' * la
2025-07-02 06:41:16.383                 elif tag == 'insert':
2025-07-02 06:41:16.383                     btags += '+' * lb
2025-07-02 06:41:16.383                 elif tag == 'equal':
2025-07-02 06:41:16.383                     atags += ' ' * la
2025-07-02 06:41:16.383                     btags += ' ' * lb
2025-07-02 06:41:16.383                 else:
2025-07-02 06:41:16.383                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.383             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.383         else:
2025-07-02 06:41:16.383             # the synch pair is identical
2025-07-02 06:41:16.384             yield '  ' + aelt
2025-07-02 06:41:16.384
2025-07-02 06:41:16.384         # pump out diffs from after the synch point
2025-07-02 06:41:16.384 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.384
2025-07-02 06:41:16.384 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.384 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.384
2025-07-02 06:41:16.384 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.384 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.384 alo = 49, ahi = 1101
2025-07-02 06:41:16.384 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.384 blo = 49, bhi = 1101
2025-07-02 06:41:16.384
2025-07-02 06:41:16.384     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.384         g = []
2025-07-02 06:41:16.384         if alo < ahi:
2025-07-02 06:41:16.384             if blo < bhi:
2025-07-02 06:41:16.384                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.384             else:
2025-07-02 06:41:16.385                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.385         elif blo < bhi:
2025-07-02 06:41:16.385             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.385
2025-07-02 06:41:16.385 >       yield from g
2025-07-02 06:41:16.385
2025-07-02 06:41:16.385 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.385 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.385
2025-07-02 06:41:16.385 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.385 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.385 alo = 49, ahi = 1101
2025-07-02 06:41:16.385 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.385 blo = 49, bhi = 1101
2025-07-02 06:41:16.385
2025-07-02 06:41:16.385     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.385         r"""
2025-07-02 06:41:16.385         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.385         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.385         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.386         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.386
2025-07-02 06:41:16.386         Example:
2025-07-02 06:41:16.386
2025-07-02 06:41:16.386         >>> d = Differ()
2025-07-02 06:41:16.386         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.386         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.386         >>> print(''.join(results), end="")
2025-07-02 06:41:16.386         - abcDefghiJkl
2025-07-02 06:41:16.386         + abcdefGhijkl
2025-07-02 06:41:16.386         """
2025-07-02 06:41:16.386
2025-07-02 06:41:16.386         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.386         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.386         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.386         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.386         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.386
2025-07-02 06:41:16.386         # search for the pair that matches best without being identical
2025-07-02 06:41:16.387         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.387         # on junk -- unless we have to)
2025-07-02 06:41:16.387         for j in range(blo, bhi):
2025-07-02 06:41:16.387             bj = b[j]
2025-07-02 06:41:16.387             cruncher.set_seq2(bj)
2025-07-02 06:41:16.387             for i in range(alo, ahi):
2025-07-02 06:41:16.387                 ai = a[i]
2025-07-02 06:41:16.387                 if ai == bj:
2025-07-02 06:41:16.387                     if eqi is None:
2025-07-02 06:41:16.387                         eqi, eqj = i, j
2025-07-02 06:41:16.387                     continue
2025-07-02 06:41:16.387                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.387                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.387                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.387                 # compares by a factor of 3.
2025-07-02 06:41:16.387                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.387                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.387                 # of the computation is cached by cruncher
2025-07-02 06:41:16.387                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.388                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.388                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.388                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.388         if best_ratio < cutoff:
2025-07-02 06:41:16.388             # no non-identical "pretty close" pair
2025-07-02 06:41:16.388             if eqi is None:
2025-07-02 06:41:16.388                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.388                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.388                 return
2025-07-02 06:41:16.388             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.388             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.388         else:
2025-07-02 06:41:16.388             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.388             eqi = None
2025-07-02 06:41:16.388
2025-07-02 06:41:16.388         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.388         # identical
2025-07-02 06:41:16.388
2025-07-02 06:41:16.388         # pump out diffs from before the synch point
2025-07-02 06:41:16.389         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.389
2025-07-02 06:41:16.389         # do intraline marking on the synch pair
2025-07-02 06:41:16.389         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.389         if eqi is None:
2025-07-02 06:41:16.389             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.389             atags = btags = ""
2025-07-02 06:41:16.389             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.389             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.389                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.389                 if tag == 'replace':
2025-07-02 06:41:16.389                     atags += '^' * la
2025-07-02 06:41:16.389                     btags += '^' * lb
2025-07-02 06:41:16.389                 elif tag == 'delete':
2025-07-02 06:41:16.389                     atags += '-' * la
2025-07-02 06:41:16.389                 elif tag == 'insert':
2025-07-02 06:41:16.389                     btags += '+' * lb
2025-07-02 06:41:16.389                 elif tag == 'equal':
2025-07-02 06:41:16.389                     atags += ' ' * la
2025-07-02 06:41:16.390                     btags += ' ' * lb
2025-07-02 06:41:16.390                 else:
2025-07-02 06:41:16.390                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.390             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.390         else:
2025-07-02 06:41:16.390             # the synch pair is identical
2025-07-02 06:41:16.390             yield '  ' + aelt
2025-07-02 06:41:16.390
2025-07-02 06:41:16.390         # pump out diffs from after the synch point
2025-07-02 06:41:16.390 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.390
2025-07-02 06:41:16.390 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.390 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.390
2025-07-02 06:41:16.390 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.390 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.390 alo = 50, ahi = 1101
2025-07-02 06:41:16.390 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.390 blo = 50, bhi = 1101
2025-07-02 06:41:16.390
2025-07-02 06:41:16.391     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.391         g = []
2025-07-02 06:41:16.391         if alo < ahi:
2025-07-02 06:41:16.391             if blo < bhi:
2025-07-02 06:41:16.391                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.391             else:
2025-07-02 06:41:16.391                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.391         elif blo < bhi:
2025-07-02 06:41:16.391             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.391
2025-07-02 06:41:16.391 >       yield from g
2025-07-02 06:41:16.391
2025-07-02 06:41:16.391 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.391 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.391
2025-07-02 06:41:16.391 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.391 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.391 alo = 50, ahi = 1101
2025-07-02 06:41:16.391 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.392 blo = 50, bhi = 1101
2025-07-02 06:41:16.392
2025-07-02 06:41:16.392     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.392         r"""
2025-07-02 06:41:16.392         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.392         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.392         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.392         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.392
2025-07-02 06:41:16.392         Example:
2025-07-02 06:41:16.392
2025-07-02 06:41:16.392         >>> d = Differ()
2025-07-02 06:41:16.392         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.392         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.392         >>> print(''.join(results), end="")
2025-07-02 06:41:16.392         - abcDefghiJkl
2025-07-02 06:41:16.392         + abcdefGhijkl
2025-07-02 06:41:16.392         """
2025-07-02 06:41:16.393
2025-07-02 06:41:16.393         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.393         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.393         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.393         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.393         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.393
2025-07-02 06:41:16.393         # search for the pair that matches best without being identical
2025-07-02 06:41:16.393         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.393         # on junk -- unless we have to)
2025-07-02 06:41:16.393         for j in range(blo, bhi):
2025-07-02 06:41:16.393             bj = b[j]
2025-07-02 06:41:16.393             cruncher.set_seq2(bj)
2025-07-02 06:41:16.393             for i in range(alo, ahi):
2025-07-02 06:41:16.393                 ai = a[i]
2025-07-02 06:41:16.393                 if ai == bj:
2025-07-02 06:41:16.393                     if eqi is None:
2025-07-02 06:41:16.393                         eqi, eqj = i, j
2025-07-02 06:41:16.393                     continue
2025-07-02 06:41:16.394                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.394                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.394                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.394                 # compares by a factor of 3.
2025-07-02 06:41:16.394                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.394                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.394                 # of the computation is cached by cruncher
2025-07-02 06:41:16.394                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.394                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.394                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.394                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.394         if best_ratio < cutoff:
2025-07-02 06:41:16.394             # no non-identical "pretty close" pair
2025-07-02 06:41:16.394             if eqi is None:
2025-07-02 06:41:16.394                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.394                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.394                 return
2025-07-02 06:41:16.394             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.394             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.394         else:
2025-07-02 06:41:16.395             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.395             eqi = None
2025-07-02 06:41:16.395
2025-07-02 06:41:16.395         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.395         # identical
2025-07-02 06:41:16.395
2025-07-02 06:41:16.395         # pump out diffs from before the synch point
2025-07-02 06:41:16.395         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.395
2025-07-02 06:41:16.395         # do intraline marking on the synch pair
2025-07-02 06:41:16.395         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.395         if eqi is None:
2025-07-02 06:41:16.395             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.395             atags = btags = ""
2025-07-02 06:41:16.395             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.395             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.395                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.395                 if tag == 'replace':
2025-07-02 06:41:16.395                     atags += '^' * la
2025-07-02 06:41:16.395                     btags += '^' * lb
2025-07-02 06:41:16.396                 elif tag == 'delete':
2025-07-02 06:41:16.396                     atags += '-' * la
2025-07-02 06:41:16.396                 elif tag == 'insert':
2025-07-02 06:41:16.396                     btags += '+' * lb
2025-07-02 06:41:16.396                 elif tag == 'equal':
2025-07-02 06:41:16.396                     atags += ' ' * la
2025-07-02 06:41:16.396                     btags += ' ' * lb
2025-07-02 06:41:16.396                 else:
2025-07-02 06:41:16.396                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.396             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.396         else:
2025-07-02 06:41:16.396             # the synch pair is identical
2025-07-02 06:41:16.396             yield '  ' + aelt
2025-07-02 06:41:16.396
2025-07-02 06:41:16.396         # pump out diffs from after the synch point
2025-07-02 06:41:16.396 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.396
2025-07-02 06:41:16.396 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.396 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.397
2025-07-02 06:41:16.397 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.397 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.397 alo = 51, ahi = 1101
2025-07-02 06:41:16.397 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.397 blo = 51, bhi = 1101
2025-07-02 06:41:16.397
2025-07-02 06:41:16.397     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.397         g = []
2025-07-02 06:41:16.397         if alo < ahi:
2025-07-02 06:41:16.397             if blo < bhi:
2025-07-02 06:41:16.397                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.397             else:
2025-07-02 06:41:16.397                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.397         elif blo < bhi:
2025-07-02 06:41:16.397             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.397
2025-07-02 06:41:16.397 >       yield from g
2025-07-02 06:41:16.398
2025-07-02 06:41:16.398 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.398 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.398
2025-07-02 06:41:16.398 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.398 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.398 alo = 51, ahi = 1101
2025-07-02 06:41:16.398 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.398 blo = 51, bhi = 1101
2025-07-02 06:41:16.398
2025-07-02 06:41:16.398     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.398         r"""
2025-07-02 06:41:16.398         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.398         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.398         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.398         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.398
2025-07-02 06:41:16.398         Example:
2025-07-02 06:41:16.398
2025-07-02 06:41:16.399         >>> d = Differ()
2025-07-02 06:41:16.399         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.399         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.399         >>> print(''.join(results), end="")
2025-07-02 06:41:16.399         - abcDefghiJkl
2025-07-02 06:41:16.399         + abcdefGhijkl
2025-07-02 06:41:16.399         """
2025-07-02 06:41:16.399
2025-07-02 06:41:16.399         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.399         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.399         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.399         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.399         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.399
2025-07-02 06:41:16.399         # search for the pair that matches best without being identical
2025-07-02 06:41:16.399         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.399         # on junk -- unless we have to)
2025-07-02 06:41:16.399         for j in range(blo, bhi):
2025-07-02 06:41:16.400             bj = b[j]
2025-07-02 06:41:16.400             cruncher.set_seq2(bj)
2025-07-02 06:41:16.400             for i in range(alo, ahi):
2025-07-02 06:41:16.400                 ai = a[i]
2025-07-02 06:41:16.400                 if ai == bj:
2025-07-02 06:41:16.400                     if eqi is None:
2025-07-02 06:41:16.400                         eqi, eqj = i, j
2025-07-02 06:41:16.400                     continue
2025-07-02 06:41:16.400                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.400                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.400                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.400                 # compares by a factor of 3.
2025-07-02 06:41:16.400                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.400                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.400                 # of the computation is cached by cruncher
2025-07-02 06:41:16.400                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.400                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.400                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.400                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.401         if best_ratio < cutoff:
2025-07-02 06:41:16.401             # no non-identical "pretty close" pair
2025-07-02 06:41:16.401             if eqi is None:
2025-07-02 06:41:16.401                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.401                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.401                 return
2025-07-02 06:41:16.401             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.401             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.401         else:
2025-07-02 06:41:16.401             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.401             eqi = None
2025-07-02 06:41:16.401
2025-07-02 06:41:16.401         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.401         # identical
2025-07-02 06:41:16.401
2025-07-02 06:41:16.401         # pump out diffs from before the synch point
2025-07-02 06:41:16.401         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.401
2025-07-02 06:41:16.401         # do intraline marking on the synch pair
2025-07-02 06:41:16.401         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.402         if eqi is None:
2025-07-02 06:41:16.402             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.402             atags = btags = ""
2025-07-02 06:41:16.402             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.402             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.402                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.402                 if tag == 'replace':
2025-07-02 06:41:16.402                     atags += '^' * la
2025-07-02 06:41:16.402                     btags += '^' * lb
2025-07-02 06:41:16.402                 elif tag == 'delete':
2025-07-02 06:41:16.402                     atags += '-' * la
2025-07-02 06:41:16.402                 elif tag == 'insert':
2025-07-02 06:41:16.402                     btags += '+' * lb
2025-07-02 06:41:16.402                 elif tag == 'equal':
2025-07-02 06:41:16.402                     atags += ' ' * la
2025-07-02 06:41:16.402                     btags += ' ' * lb
2025-07-02 06:41:16.402                 else:
2025-07-02 06:41:16.402                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.402             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.403         else:
2025-07-02 06:41:16.403             # the synch pair is identical
2025-07-02 06:41:16.403             yield '  ' + aelt
2025-07-02 06:41:16.403
2025-07-02 06:41:16.403         # pump out diffs from after the synch point
2025-07-02 06:41:16.403 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.403
2025-07-02 06:41:16.403 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.403 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.403
2025-07-02 06:41:16.403 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.403 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.403 alo = 52, ahi = 1101
2025-07-02 06:41:16.403 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.403 blo = 52, bhi = 1101
2025-07-02 06:41:16.403
2025-07-02 06:41:16.403     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.403         g = []
2025-07-02 06:41:16.403         if alo < ahi:
2025-07-02 06:41:16.403             if blo < bhi:
2025-07-02 06:41:16.404                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.404             else:
2025-07-02 06:41:16.404                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.404         elif blo < bhi:
2025-07-02 06:41:16.404             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.404
2025-07-02 06:41:16.404 >       yield from g
2025-07-02 06:41:16.404
2025-07-02 06:41:16.404 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.404 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.404
2025-07-02 06:41:16.404 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.404 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.404 alo = 52, ahi = 1101
2025-07-02 06:41:16.404 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.404 blo = 52, bhi = 1101
2025-07-02 06:41:16.404
2025-07-02 06:41:16.404     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.404         r"""
2025-07-02 06:41:16.405         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.405         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.405         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.405         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.405
2025-07-02 06:41:16.405         Example:
2025-07-02 06:41:16.405
2025-07-02 06:41:16.405         >>> d = Differ()
2025-07-02 06:41:16.405         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.405         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.405         >>> print(''.join(results), end="")
2025-07-02 06:41:16.405         - abcDefghiJkl
2025-07-02 06:41:16.405         + abcdefGhijkl
2025-07-02 06:41:16.405         """
2025-07-02 06:41:16.405
2025-07-02 06:41:16.405         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.405         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.406         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.406         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.406         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.406
2025-07-02 06:41:16.406         # search for the pair that matches best without being identical
2025-07-02 06:41:16.406         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.406         # on junk -- unless we have to)
2025-07-02 06:41:16.406         for j in range(blo, bhi):
2025-07-02 06:41:16.406             bj = b[j]
2025-07-02 06:41:16.406             cruncher.set_seq2(bj)
2025-07-02 06:41:16.406             for i in range(alo, ahi):
2025-07-02 06:41:16.406                 ai = a[i]
2025-07-02 06:41:16.406                 if ai == bj:
2025-07-02 06:41:16.406                     if eqi is None:
2025-07-02 06:41:16.406                         eqi, eqj = i, j
2025-07-02 06:41:16.406                     continue
2025-07-02 06:41:16.406                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.406                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.406                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.407                 # compares by a factor of 3.
2025-07-02 06:41:16.407                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.407                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.407                 # of the computation is cached by cruncher
2025-07-02 06:41:16.407                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.407                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.407                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.407                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.407         if best_ratio < cutoff:
2025-07-02 06:41:16.407             # no non-identical "pretty close" pair
2025-07-02 06:41:16.407             if eqi is None:
2025-07-02 06:41:16.407                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.407                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.407                 return
2025-07-02 06:41:16.407             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.407             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.407         else:
2025-07-02 06:41:16.407             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.407             eqi = None
2025-07-02 06:41:16.408
2025-07-02 06:41:16.408         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.408         # identical
2025-07-02 06:41:16.408
2025-07-02 06:41:16.408         # pump out diffs from before the synch point
2025-07-02 06:41:16.408         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.408
2025-07-02 06:41:16.408         # do intraline marking on the synch pair
2025-07-02 06:41:16.408         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.408         if eqi is None:
2025-07-02 06:41:16.408             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.408             atags = btags = ""
2025-07-02 06:41:16.408             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.408             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.408                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.408                 if tag == 'replace':
2025-07-02 06:41:16.408                     atags += '^' * la
2025-07-02 06:41:16.408                     btags += '^' * lb
2025-07-02 06:41:16.408                 elif tag == 'delete':
2025-07-02 06:41:16.408                     atags += '-' * la
2025-07-02 06:41:16.409                 elif tag == 'insert':
2025-07-02 06:41:16.409                     btags += '+' * lb
2025-07-02 06:41:16.409                 elif tag == 'equal':
2025-07-02 06:41:16.409                     atags += ' ' * la
2025-07-02 06:41:16.409                     btags += ' ' * lb
2025-07-02 06:41:16.409                 else:
2025-07-02 06:41:16.409                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.409             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.409         else:
2025-07-02 06:41:16.409             # the synch pair is identical
2025-07-02 06:41:16.409             yield '  ' + aelt
2025-07-02 06:41:16.409
2025-07-02 06:41:16.409         # pump out diffs from after the synch point
2025-07-02 06:41:16.409 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.409
2025-07-02 06:41:16.409 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.409 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.409
2025-07-02 06:41:16.409 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.409 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.410 alo = 53, ahi = 1101
2025-07-02 06:41:16.410 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.410 blo = 53, bhi = 1101
2025-07-02 06:41:16.410
2025-07-02 06:41:16.410     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.410         g = []
2025-07-02 06:41:16.410         if alo < ahi:
2025-07-02 06:41:16.410             if blo < bhi:
2025-07-02 06:41:16.410                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.410             else:
2025-07-02 06:41:16.410                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.410         elif blo < bhi:
2025-07-02 06:41:16.410             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.410
2025-07-02 06:41:16.410 >       yield from g
2025-07-02 06:41:16.410
2025-07-02 06:41:16.410 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.410 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.410
2025-07-02 06:41:16.411 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.411 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.411 alo = 53, ahi = 1101
2025-07-02 06:41:16.411 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.411 blo = 53, bhi = 1101
2025-07-02 06:41:16.411
2025-07-02 06:41:16.411     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.411         r"""
2025-07-02 06:41:16.411         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.411         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.411         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.411         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.411
2025-07-02 06:41:16.411         Example:
2025-07-02 06:41:16.411
2025-07-02 06:41:16.411         >>> d = Differ()
2025-07-02 06:41:16.411         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.411         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.411         >>> print(''.join(results), end="")
2025-07-02 06:41:16.412         - abcDefghiJkl
2025-07-02 06:41:16.412         + abcdefGhijkl
2025-07-02 06:41:16.412         """
2025-07-02 06:41:16.412
2025-07-02 06:41:16.412         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.412         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.412         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.412         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.412         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.412
2025-07-02 06:41:16.412         # search for the pair that matches best without being identical
2025-07-02 06:41:16.412         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.412         # on junk -- unless we have to)
2025-07-02 06:41:16.412         for j in range(blo, bhi):
2025-07-02 06:41:16.412             bj = b[j]
2025-07-02 06:41:16.412             cruncher.set_seq2(bj)
2025-07-02 06:41:16.412             for i in range(alo, ahi):
2025-07-02 06:41:16.413                 ai = a[i]
2025-07-02 06:41:16.413                 if ai == bj:
2025-07-02 06:41:16.413                     if eqi is None:
2025-07-02 06:41:16.413                         eqi, eqj = i, j
2025-07-02 06:41:16.413                     continue
2025-07-02 06:41:16.413                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.413                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.413                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.413                 # compares by a factor of 3.
2025-07-02 06:41:16.413                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.413                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.413                 # of the computation is cached by cruncher
2025-07-02 06:41:16.413                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.413                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.413                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.413                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.413         if best_ratio < cutoff:
2025-07-02 06:41:16.413             # no non-identical "pretty close" pair
2025-07-02 06:41:16.413             if eqi is None:
2025-07-02 06:41:16.414                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.414                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.414                 return
2025-07-02 06:41:16.414             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.414             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.414         else:
2025-07-02 06:41:16.414             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.414             eqi = None
2025-07-02 06:41:16.414
2025-07-02 06:41:16.414         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.414         # identical
2025-07-02 06:41:16.414
2025-07-02 06:41:16.414         # pump out diffs from before the synch point
2025-07-02 06:41:16.414         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.414
2025-07-02 06:41:16.414         # do intraline marking on the synch pair
2025-07-02 06:41:16.414         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.414         if eqi is None:
2025-07-02 06:41:16.414             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.415             atags = btags = ""
2025-07-02 06:41:16.415             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.415             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.415                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.415                 if tag == 'replace':
2025-07-02 06:41:16.415                     atags += '^' * la
2025-07-02 06:41:16.415                     btags += '^' * lb
2025-07-02 06:41:16.415                 elif tag == 'delete':
2025-07-02 06:41:16.415                     atags += '-' * la
2025-07-02 06:41:16.415                 elif tag == 'insert':
2025-07-02 06:41:16.415                     btags += '+' * lb
2025-07-02 06:41:16.415                 elif tag == 'equal':
2025-07-02 06:41:16.415                     atags += ' ' * la
2025-07-02 06:41:16.415                     btags += ' ' * lb
2025-07-02 06:41:16.415                 else:
2025-07-02 06:41:16.415                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.415             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.415         else:
2025-07-02 06:41:16.415             # the synch pair is identical
2025-07-02 06:41:16.415             yield '  ' + aelt
2025-07-02 06:41:16.416
2025-07-02 06:41:16.416         # pump out diffs from after the synch point
2025-07-02 06:41:16.416 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.416
2025-07-02 06:41:16.416 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.416 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.416
2025-07-02 06:41:16.416 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.416 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.416 alo = 54, ahi = 1101
2025-07-02 06:41:16.416 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.416 blo = 54, bhi = 1101
2025-07-02 06:41:16.416
2025-07-02 06:41:16.416     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.416         g = []
2025-07-02 06:41:16.416         if alo < ahi:
2025-07-02 06:41:16.416             if blo < bhi:
2025-07-02 06:41:16.416                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.416             else:
2025-07-02 06:41:16.417                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.417         elif blo < bhi:
2025-07-02 06:41:16.417             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.417
2025-07-02 06:41:16.417 >       yield from g
2025-07-02 06:41:16.417
2025-07-02 06:41:16.417 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.417 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.417
2025-07-02 06:41:16.417 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.417 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.417 alo = 54, ahi = 1101
2025-07-02 06:41:16.417 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.417 blo = 54, bhi = 1101
2025-07-02 06:41:16.417
2025-07-02 06:41:16.417     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.417         r"""
2025-07-02 06:41:16.417         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.417         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.417         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.418         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.418
2025-07-02 06:41:16.418         Example:
2025-07-02 06:41:16.418
2025-07-02 06:41:16.418         >>> d = Differ()
2025-07-02 06:41:16.418         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.418         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.418         >>> print(''.join(results), end="")
2025-07-02 06:41:16.418         - abcDefghiJkl
2025-07-02 06:41:16.418         + abcdefGhijkl
2025-07-02 06:41:16.418         """
2025-07-02 06:41:16.418
2025-07-02 06:41:16.418         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.418         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.418         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.418         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.418         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.419
2025-07-02 06:41:16.419         # search for the pair that matches best without being identical
2025-07-02 06:41:16.419         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.419         # on junk -- unless we have to)
2025-07-02 06:41:16.419         for j in range(blo, bhi):
2025-07-02 06:41:16.419             bj = b[j]
2025-07-02 06:41:16.419             cruncher.set_seq2(bj)
2025-07-02 06:41:16.419             for i in range(alo, ahi):
2025-07-02 06:41:16.419                 ai = a[i]
2025-07-02 06:41:16.419                 if ai == bj:
2025-07-02 06:41:16.419                     if eqi is None:
2025-07-02 06:41:16.419                         eqi, eqj = i, j
2025-07-02 06:41:16.419                     continue
2025-07-02 06:41:16.419                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.419                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.419                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.419                 # compares by a factor of 3.
2025-07-02 06:41:16.419                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.419                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.419                 # of the computation is cached by cruncher
2025-07-02 06:41:16.420                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.420                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.420                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.420                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.420         if best_ratio < cutoff:
2025-07-02 06:41:16.420             # no non-identical "pretty close" pair
2025-07-02 06:41:16.420             if eqi is None:
2025-07-02 06:41:16.420                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.420                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.420                 return
2025-07-02 06:41:16.420             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.420             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.420         else:
2025-07-02 06:41:16.420             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.420             eqi = None
2025-07-02 06:41:16.420
2025-07-02 06:41:16.420         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.420         # identical
2025-07-02 06:41:16.420
2025-07-02 06:41:16.420         # pump out diffs from before the synch point
2025-07-02 06:41:16.421         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.421
2025-07-02 06:41:16.421         # do intraline marking on the synch pair
2025-07-02 06:41:16.421         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.421         if eqi is None:
2025-07-02 06:41:16.421             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.421             atags = btags = ""
2025-07-02 06:41:16.421             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.421             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.421                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.421                 if tag == 'replace':
2025-07-02 06:41:16.421                     atags += '^' * la
2025-07-02 06:41:16.421                     btags += '^' * lb
2025-07-02 06:41:16.421                 elif tag == 'delete':
2025-07-02 06:41:16.421                     atags += '-' * la
2025-07-02 06:41:16.421                 elif tag == 'insert':
2025-07-02 06:41:16.421                     btags += '+' * lb
2025-07-02 06:41:16.421                 elif tag == 'equal':
2025-07-02 06:41:16.421                     atags += ' ' * la
2025-07-02 06:41:16.422                     btags += ' ' * lb
2025-07-02 06:41:16.422                 else:
2025-07-02 06:41:16.422                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.422             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.422         else:
2025-07-02 06:41:16.422             # the synch pair is identical
2025-07-02 06:41:16.422             yield '  ' + aelt
2025-07-02 06:41:16.422
2025-07-02 06:41:16.422         # pump out diffs from after the synch point
2025-07-02 06:41:16.422 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.422
2025-07-02 06:41:16.422 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.422 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.422
2025-07-02 06:41:16.422 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.422 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.422 alo = 55, ahi = 1101
2025-07-02 06:41:16.422 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.422 blo = 55, bhi = 1101
2025-07-02 06:41:16.422
2025-07-02 06:41:16.423     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.423         g = []
2025-07-02 06:41:16.423         if alo < ahi:
2025-07-02 06:41:16.423             if blo < bhi:
2025-07-02 06:41:16.423                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.423             else:
2025-07-02 06:41:16.423                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.423         elif blo < bhi:
2025-07-02 06:41:16.423             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.423
2025-07-02 06:41:16.423 >       yield from g
2025-07-02 06:41:16.423
2025-07-02 06:41:16.423 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.423 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.423
2025-07-02 06:41:16.423 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.423 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.423 alo = 55, ahi = 1101
2025-07-02 06:41:16.424 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.424 blo = 55, bhi = 1101
2025-07-02 06:41:16.424
2025-07-02 06:41:16.424     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.424         r"""
2025-07-02 06:41:16.424         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.424         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.424         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.424         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.424
2025-07-02 06:41:16.424         Example:
2025-07-02 06:41:16.424
2025-07-02 06:41:16.424         >>> d = Differ()
2025-07-02 06:41:16.424         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.424         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.424         >>> print(''.join(results), end="")
2025-07-02 06:41:16.424         - abcDefghiJkl
2025-07-02 06:41:16.424         + abcdefGhijkl
2025-07-02 06:41:16.425         """
2025-07-02 06:41:16.425
2025-07-02 06:41:16.425         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.425         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.425         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.425         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.425         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.425
2025-07-02 06:41:16.425         # search for the pair that matches best without being identical
2025-07-02 06:41:16.425         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.425         # on junk -- unless we have to)
2025-07-02 06:41:16.425         for j in range(blo, bhi):
2025-07-02 06:41:16.425             bj = b[j]
2025-07-02 06:41:16.425             cruncher.set_seq2(bj)
2025-07-02 06:41:16.425             for i in range(alo, ahi):
2025-07-02 06:41:16.425                 ai = a[i]
2025-07-02 06:41:16.425                 if ai == bj:
2025-07-02 06:41:16.425                     if eqi is None:
2025-07-02 06:41:16.425                         eqi, eqj = i, j
2025-07-02 06:41:16.426                     continue
2025-07-02 06:41:16.426                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.426                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.426                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.426                 # compares by a factor of 3.
2025-07-02 06:41:16.426                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.426                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.426                 # of the computation is cached by cruncher
2025-07-02 06:41:16.426                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.426                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.426                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.426                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.426         if best_ratio < cutoff:
2025-07-02 06:41:16.426             # no non-identical "pretty close" pair
2025-07-02 06:41:16.426             if eqi is None:
2025-07-02 06:41:16.426                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.426                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.426                 return
2025-07-02 06:41:16.426             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.426             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.427         else:
2025-07-02 06:41:16.427             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.427             eqi = None
2025-07-02 06:41:16.427
2025-07-02 06:41:16.427         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.427         # identical
2025-07-02 06:41:16.427
2025-07-02 06:41:16.427         # pump out diffs from before the synch point
2025-07-02 06:41:16.427         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.427
2025-07-02 06:41:16.427         # do intraline marking on the synch pair
2025-07-02 06:41:16.427         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.427         if eqi is None:
2025-07-02 06:41:16.427             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.427             atags = btags = ""
2025-07-02 06:41:16.427             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.427             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.427                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.427                 if tag == 'replace':
2025-07-02 06:41:16.427                     atags += '^' * la
2025-07-02 06:41:16.428                     btags += '^' * lb
2025-07-02 06:41:16.428                 elif tag == 'delete':
2025-07-02 06:41:16.428                     atags += '-' * la
2025-07-02 06:41:16.428                 elif tag == 'insert':
2025-07-02 06:41:16.428                     btags += '+' * lb
2025-07-02 06:41:16.428                 elif tag == 'equal':
2025-07-02 06:41:16.428                     atags += ' ' * la
2025-07-02 06:41:16.428                     btags += ' ' * lb
2025-07-02 06:41:16.428                 else:
2025-07-02 06:41:16.428                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.428             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.428         else:
2025-07-02 06:41:16.428             # the synch pair is identical
2025-07-02 06:41:16.428             yield '  ' + aelt
2025-07-02 06:41:16.428
2025-07-02 06:41:16.428         # pump out diffs from after the synch point
2025-07-02 06:41:16.428 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.428
2025-07-02 06:41:16.429 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.429 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.429
2025-07-02 06:41:16.429 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.429 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.429 alo = 56, ahi = 1101
2025-07-02 06:41:16.429 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.429 blo = 56, bhi = 1101
2025-07-02 06:41:16.429
2025-07-02 06:41:16.429     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.429         g = []
2025-07-02 06:41:16.429         if alo < ahi:
2025-07-02 06:41:16.429             if blo < bhi:
2025-07-02 06:41:16.429                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.429             else:
2025-07-02 06:41:16.429                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.429         elif blo < bhi:
2025-07-02 06:41:16.429             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.429
2025-07-02 06:41:16.430 >       yield from g
2025-07-02 06:41:16.430
2025-07-02 06:41:16.430 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.430 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.430
2025-07-02 06:41:16.430 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.430 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.430 alo = 56, ahi = 1101
2025-07-02 06:41:16.430 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.430 blo = 56, bhi = 1101
2025-07-02 06:41:16.430
2025-07-02 06:41:16.430     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.430         r"""
2025-07-02 06:41:16.430         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.430         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.430         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.430         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.430
2025-07-02 06:41:16.430         Example:
2025-07-02 06:41:16.431
2025-07-02 06:41:16.431         >>> d = Differ()
2025-07-02 06:41:16.431         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.431         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.431         >>> print(''.join(results), end="")
2025-07-02 06:41:16.431         - abcDefghiJkl
2025-07-02 06:41:16.431         + abcdefGhijkl
2025-07-02 06:41:16.431         """
2025-07-02 06:41:16.431
2025-07-02 06:41:16.431         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.431         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.431         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.431         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.431         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.431
2025-07-02 06:41:16.431         # search for the pair that matches best without being identical
2025-07-02 06:41:16.431         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.432         # on junk -- unless we have to)
2025-07-02 06:41:16.432         for j in range(blo, bhi):
2025-07-02 06:41:16.432             bj = b[j]
2025-07-02 06:41:16.432             cruncher.set_seq2(bj)
2025-07-02 06:41:16.432             for i in range(alo, ahi):
2025-07-02 06:41:16.432                 ai = a[i]
2025-07-02 06:41:16.432                 if ai == bj:
2025-07-02 06:41:16.432                     if eqi is None:
2025-07-02 06:41:16.432                         eqi, eqj = i, j
2025-07-02 06:41:16.432                     continue
2025-07-02 06:41:16.432                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.432                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.432                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.432                 # compares by a factor of 3.
2025-07-02 06:41:16.432                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.432                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.432                 # of the computation is cached by cruncher
2025-07-02 06:41:16.432                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.433                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.433                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.433                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.433         if best_ratio < cutoff:
2025-07-02 06:41:16.433             # no non-identical "pretty close" pair
2025-07-02 06:41:16.433             if eqi is None:
2025-07-02 06:41:16.433                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.433                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.433                 return
2025-07-02 06:41:16.433             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.433             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.433         else:
2025-07-02 06:41:16.433             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.433             eqi = None
2025-07-02 06:41:16.433
2025-07-02 06:41:16.433         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.433         # identical
2025-07-02 06:41:16.433
2025-07-02 06:41:16.433         # pump out diffs from before the synch point
2025-07-02 06:41:16.434         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.434
2025-07-02 06:41:16.434         # do intraline marking on the synch pair
2025-07-02 06:41:16.434         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.434         if eqi is None:
2025-07-02 06:41:16.434             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.434             atags = btags = ""
2025-07-02 06:41:16.434             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.434             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.434                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.434                 if tag == 'replace':
2025-07-02 06:41:16.434                     atags += '^' * la
2025-07-02 06:41:16.434                     btags += '^' * lb
2025-07-02 06:41:16.434                 elif tag == 'delete':
2025-07-02 06:41:16.434                     atags += '-' * la
2025-07-02 06:41:16.434                 elif tag == 'insert':
2025-07-02 06:41:16.434                     btags += '+' * lb
2025-07-02 06:41:16.434                 elif tag == 'equal':
2025-07-02 06:41:16.434                     atags += ' ' * la
2025-07-02 06:41:16.435                     btags += ' ' * lb
2025-07-02 06:41:16.435                 else:
2025-07-02 06:41:16.435                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.435             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.435         else:
2025-07-02 06:41:16.435             # the synch pair is identical
2025-07-02 06:41:16.435             yield '  ' + aelt
2025-07-02 06:41:16.435
2025-07-02 06:41:16.435         # pump out diffs from after the synch point
2025-07-02 06:41:16.435 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.435
2025-07-02 06:41:16.435 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.435 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.435
2025-07-02 06:41:16.435 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.435 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.435 alo = 57, ahi = 1101
2025-07-02 06:41:16.436 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.436 blo = 57, bhi = 1101
2025-07-02 06:41:16.436
2025-07-02 06:41:16.436     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.436         g = []
2025-07-02 06:41:16.436         if alo < ahi:
2025-07-02 06:41:16.436             if blo < bhi:
2025-07-02 06:41:16.436                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.436             else:
2025-07-02 06:41:16.436                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.436         elif blo < bhi:
2025-07-02 06:41:16.436             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.436
2025-07-02 06:41:16.436 >       yield from g
2025-07-02 06:41:16.436
2025-07-02 06:41:16.436 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.436 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.436
2025-07-02 06:41:16.436 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.437 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.437 alo = 57, ahi = 1101
2025-07-02 06:41:16.437 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.437 blo = 57, bhi = 1101
2025-07-02 06:41:16.437
2025-07-02 06:41:16.437     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.437         r"""
2025-07-02 06:41:16.437         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.437         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.437         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.437         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.437
2025-07-02 06:41:16.437         Example:
2025-07-02 06:41:16.437
2025-07-02 06:41:16.437         >>> d = Differ()
2025-07-02 06:41:16.437         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.437         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.437         >>> print(''.join(results), end="")
2025-07-02 06:41:16.437         - abcDefghiJkl
2025-07-02 06:41:16.438         + abcdefGhijkl
2025-07-02 06:41:16.438         """
2025-07-02 06:41:16.438
2025-07-02 06:41:16.438         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.438         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.438         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.438         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.438         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.438
2025-07-02 06:41:16.438         # search for the pair that matches best without being identical
2025-07-02 06:41:16.438         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.438         # on junk -- unless we have to)
2025-07-02 06:41:16.438         for j in range(blo, bhi):
2025-07-02 06:41:16.438             bj = b[j]
2025-07-02 06:41:16.438             cruncher.set_seq2(bj)
2025-07-02 06:41:16.438             for i in range(alo, ahi):
2025-07-02 06:41:16.438                 ai = a[i]
2025-07-02 06:41:16.439                 if ai == bj:
2025-07-02 06:41:16.439                     if eqi is None:
2025-07-02 06:41:16.439                         eqi, eqj = i, j
2025-07-02 06:41:16.439                     continue
2025-07-02 06:41:16.439                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.439                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.439                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.439                 # compares by a factor of 3.
2025-07-02 06:41:16.439                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.439                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.439                 # of the computation is cached by cruncher
2025-07-02 06:41:16.439                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.439                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.439                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.439                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.439         if best_ratio < cutoff:
2025-07-02 06:41:16.439             # no non-identical "pretty close" pair
2025-07-02 06:41:16.439             if eqi is None:
2025-07-02 06:41:16.439                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.440                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.440                 return
2025-07-02 06:41:16.440             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.440             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.440         else:
2025-07-02 06:41:16.440             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.440             eqi = None
2025-07-02 06:41:16.440
2025-07-02 06:41:16.440         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.440         # identical
2025-07-02 06:41:16.440
2025-07-02 06:41:16.440         # pump out diffs from before the synch point
2025-07-02 06:41:16.440         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.440
2025-07-02 06:41:16.440         # do intraline marking on the synch pair
2025-07-02 06:41:16.440         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.440         if eqi is None:
2025-07-02 06:41:16.440             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.440             atags = btags = ""
2025-07-02 06:41:16.440             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.441             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.441                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.441                 if tag == 'replace':
2025-07-02 06:41:16.441                     atags += '^' * la
2025-07-02 06:41:16.441                     btags += '^' * lb
2025-07-02 06:41:16.441                 elif tag == 'delete':
2025-07-02 06:41:16.441                     atags += '-' * la
2025-07-02 06:41:16.441                 elif tag == 'insert':
2025-07-02 06:41:16.441                     btags += '+' * lb
2025-07-02 06:41:16.441                 elif tag == 'equal':
2025-07-02 06:41:16.441                     atags += ' ' * la
2025-07-02 06:41:16.441                     btags += ' ' * lb
2025-07-02 06:41:16.441                 else:
2025-07-02 06:41:16.441                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.441             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.441         else:
2025-07-02 06:41:16.441             # the synch pair is identical
2025-07-02 06:41:16.441             yield '  ' + aelt
2025-07-02 06:41:16.442
2025-07-02 06:41:16.442         # pump out diffs from after the synch point
2025-07-02 06:41:16.442 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.442
2025-07-02 06:41:16.442 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.442 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.442
2025-07-02 06:41:16.442 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.442 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.442 alo = 58, ahi = 1101
2025-07-02 06:41:16.442 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.442 blo = 58, bhi = 1101
2025-07-02 06:41:16.442
2025-07-02 06:41:16.442     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.442         g = []
2025-07-02 06:41:16.442         if alo < ahi:
2025-07-02 06:41:16.442             if blo < bhi:
2025-07-02 06:41:16.442                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.442             else:
2025-07-02 06:41:16.443                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.443         elif blo < bhi:
2025-07-02 06:41:16.443             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.443
2025-07-02 06:41:16.443 >       yield from g
2025-07-02 06:41:16.443
2025-07-02 06:41:16.443 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.443 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.443
2025-07-02 06:41:16.443 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.443 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.443 alo = 58, ahi = 1101
2025-07-02 06:41:16.443 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.443 blo = 58, bhi = 1101
2025-07-02 06:41:16.443
2025-07-02 06:41:16.443     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.443         r"""
2025-07-02 06:41:16.443         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.443         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.444         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.444         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.444
2025-07-02 06:41:16.444         Example:
2025-07-02 06:41:16.444
2025-07-02 06:41:16.444         >>> d = Differ()
2025-07-02 06:41:16.444         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.444         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.444         >>> print(''.join(results), end="")
2025-07-02 06:41:16.444         - abcDefghiJkl
2025-07-02 06:41:16.444         + abcdefGhijkl
2025-07-02 06:41:16.444         """
2025-07-02 06:41:16.444
2025-07-02 06:41:16.444         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.444         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.444         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.444         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.444         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.445
2025-07-02 06:41:16.445         # search for the pair that matches best without being identical
2025-07-02 06:41:16.445         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.445         # on junk -- unless we have to)
2025-07-02 06:41:16.445         for j in range(blo, bhi):
2025-07-02 06:41:16.445             bj = b[j]
2025-07-02 06:41:16.445             cruncher.set_seq2(bj)
2025-07-02 06:41:16.445             for i in range(alo, ahi):
2025-07-02 06:41:16.445                 ai = a[i]
2025-07-02 06:41:16.445                 if ai == bj:
2025-07-02 06:41:16.445                     if eqi is None:
2025-07-02 06:41:16.445                         eqi, eqj = i, j
2025-07-02 06:41:16.445                     continue
2025-07-02 06:41:16.445                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.445                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.445                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.445                 # compares by a factor of 3.
2025-07-02 06:41:16.445                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.445                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.445                 # of the computation is cached by cruncher
2025-07-02 06:41:16.446                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.446                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.446                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.446                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.446         if best_ratio < cutoff:
2025-07-02 06:41:16.446             # no non-identical "pretty close" pair
2025-07-02 06:41:16.446             if eqi is None:
2025-07-02 06:41:16.446                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.446                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.446                 return
2025-07-02 06:41:16.446             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.446             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.446         else:
2025-07-02 06:41:16.446             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.446             eqi = None
2025-07-02 06:41:16.446
2025-07-02 06:41:16.446         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.446         # identical
2025-07-02 06:41:16.446
2025-07-02 06:41:16.446         # pump out diffs from before the synch point
2025-07-02 06:41:16.446         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.447
2025-07-02 06:41:16.447         # do intraline marking on the synch pair
2025-07-02 06:41:16.447         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.447         if eqi is None:
2025-07-02 06:41:16.447             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.447             atags = btags = ""
2025-07-02 06:41:16.447             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.447             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.447                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.447                 if tag == 'replace':
2025-07-02 06:41:16.447                     atags += '^' * la
2025-07-02 06:41:16.447                     btags += '^' * lb
2025-07-02 06:41:16.447                 elif tag == 'delete':
2025-07-02 06:41:16.447                     atags += '-' * la
2025-07-02 06:41:16.447                 elif tag == 'insert':
2025-07-02 06:41:16.447                     btags += '+' * lb
2025-07-02 06:41:16.447                 elif tag == 'equal':
2025-07-02 06:41:16.447                     atags += ' ' * la
2025-07-02 06:41:16.447                     btags += ' ' * lb
2025-07-02 06:41:16.447                 else:
2025-07-02 06:41:16.448                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.448             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.448         else:
2025-07-02 06:41:16.448             # the synch pair is identical
2025-07-02 06:41:16.448             yield '  ' + aelt
2025-07-02 06:41:16.448
2025-07-02 06:41:16.448         # pump out diffs from after the synch point
2025-07-02 06:41:16.448 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.448
2025-07-02 06:41:16.448 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.448 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.448
2025-07-02 06:41:16.448 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.448 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.448 alo = 59, ahi = 1101
2025-07-02 06:41:16.448 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.448 blo = 59, bhi = 1101
2025-07-02 06:41:16.448
2025-07-02 06:41:16.448     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.448         g = []
2025-07-02 06:41:16.449         if alo < ahi:
2025-07-02 06:41:16.449             if blo < bhi:
2025-07-02 06:41:16.449                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.449             else:
2025-07-02 06:41:16.449                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.449         elif blo < bhi:
2025-07-02 06:41:16.449             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.449
2025-07-02 06:41:16.449 >       yield from g
2025-07-02 06:41:16.449
2025-07-02 06:41:16.449 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.449 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.449
2025-07-02 06:41:16.449 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.449 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.449 alo = 59, ahi = 1101
2025-07-02 06:41:16.449 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.449 blo = 59, bhi = 1101
2025-07-02 06:41:16.449
2025-07-02 06:41:16.449     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.449         r"""
2025-07-02 06:41:16.450         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.450         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.450         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.450         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.450
2025-07-02 06:41:16.450         Example:
2025-07-02 06:41:16.450
2025-07-02 06:41:16.450         >>> d = Differ()
2025-07-02 06:41:16.450         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.450         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.450         >>> print(''.join(results), end="")
2025-07-02 06:41:16.450         - abcDefghiJkl
2025-07-02 06:41:16.450         + abcdefGhijkl
2025-07-02 06:41:16.450         """
2025-07-02 06:41:16.450
2025-07-02 06:41:16.450         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.451         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.451         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.451         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.451         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.451
2025-07-02 06:41:16.451         # search for the pair that matches best without being identical
2025-07-02 06:41:16.451         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.451         # on junk -- unless we have to)
2025-07-02 06:41:16.451         for j in range(blo, bhi):
2025-07-02 06:41:16.451             bj = b[j]
2025-07-02 06:41:16.451             cruncher.set_seq2(bj)
2025-07-02 06:41:16.451             for i in range(alo, ahi):
2025-07-02 06:41:16.451                 ai = a[i]
2025-07-02 06:41:16.451                 if ai == bj:
2025-07-02 06:41:16.451                     if eqi is None:
2025-07-02 06:41:16.451                         eqi, eqj = i, j
2025-07-02 06:41:16.451                     continue
2025-07-02 06:41:16.451                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.451                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.452                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.452                 # compares by a factor of 3.
2025-07-02 06:41:16.452                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.452                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.452                 # of the computation is cached by cruncher
2025-07-02 06:41:16.452                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.452                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.452                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.452                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.452         if best_ratio < cutoff:
2025-07-02 06:41:16.452             # no non-identical "pretty close" pair
2025-07-02 06:41:16.452             if eqi is None:
2025-07-02 06:41:16.452                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.452                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.452                 return
2025-07-02 06:41:16.452             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.452             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.452         else:
2025-07-02 06:41:16.452             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.452             eqi = None
2025-07-02 06:41:16.453
2025-07-02 06:41:16.453         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.453         # identical
2025-07-02 06:41:16.453
2025-07-02 06:41:16.453         # pump out diffs from before the synch point
2025-07-02 06:41:16.453         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.453
2025-07-02 06:41:16.453         # do intraline marking on the synch pair
2025-07-02 06:41:16.453         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.453         if eqi is None:
2025-07-02 06:41:16.453             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.453             atags = btags = ""
2025-07-02 06:41:16.453             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.453             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.453                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.453                 if tag == 'replace':
2025-07-02 06:41:16.453                     atags += '^' * la
2025-07-02 06:41:16.453                     btags += '^' * lb
2025-07-02 06:41:16.453                 elif tag == 'delete':
2025-07-02 06:41:16.453                     atags += '-' * la
2025-07-02 06:41:16.454                 elif tag == 'insert':
2025-07-02 06:41:16.454                     btags += '+' * lb
2025-07-02 06:41:16.454                 elif tag == 'equal':
2025-07-02 06:41:16.454                     atags += ' ' * la
2025-07-02 06:41:16.454                     btags += ' ' * lb
2025-07-02 06:41:16.454                 else:
2025-07-02 06:41:16.454                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.454             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.454         else:
2025-07-02 06:41:16.454             # the synch pair is identical
2025-07-02 06:41:16.454             yield '  ' + aelt
2025-07-02 06:41:16.454
2025-07-02 06:41:16.454         # pump out diffs from after the synch point
2025-07-02 06:41:16.454 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.454
2025-07-02 06:41:16.454 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.454 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.454
2025-07-02 06:41:16.454 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.455 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.455 alo = 60, ahi = 1101
2025-07-02 06:41:16.455 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.455 blo = 60, bhi = 1101
2025-07-02 06:41:16.455
2025-07-02 06:41:16.455     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.455         g = []
2025-07-02 06:41:16.455         if alo < ahi:
2025-07-02 06:41:16.455             if blo < bhi:
2025-07-02 06:41:16.455                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.455             else:
2025-07-02 06:41:16.455                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.455         elif blo < bhi:
2025-07-02 06:41:16.455             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.455
2025-07-02 06:41:16.455 >       yield from g
2025-07-02 06:41:16.455
2025-07-02 06:41:16.455 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.455 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.455
2025-07-02 06:41:16.456 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.456 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.456 alo = 60, ahi = 1101
2025-07-02 06:41:16.456 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.456 blo = 60, bhi = 1101
2025-07-02 06:41:16.456
2025-07-02 06:41:16.456     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.456         r"""
2025-07-02 06:41:16.456         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.456         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.456         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.456         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.456
2025-07-02 06:41:16.456         Example:
2025-07-02 06:41:16.456
2025-07-02 06:41:16.456         >>> d = Differ()
2025-07-02 06:41:16.456         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.456         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.456         >>> print(''.join(results), end="")
2025-07-02 06:41:16.457         - abcDefghiJkl
2025-07-02 06:41:16.457         + abcdefGhijkl
2025-07-02 06:41:16.457         """
2025-07-02 06:41:16.457
2025-07-02 06:41:16.457         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.457         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.457         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.457         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.457         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.457
2025-07-02 06:41:16.457         # search for the pair that matches best without being identical
2025-07-02 06:41:16.457         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.457         # on junk -- unless we have to)
2025-07-02 06:41:16.457         for j in range(blo, bhi):
2025-07-02 06:41:16.457             bj = b[j]
2025-07-02 06:41:16.457             cruncher.set_seq2(bj)
2025-07-02 06:41:16.457             for i in range(alo, ahi):
2025-07-02 06:41:16.457                 ai = a[i]
2025-07-02 06:41:16.458                 if ai == bj:
2025-07-02 06:41:16.458                     if eqi is None:
2025-07-02 06:41:16.458                         eqi, eqj = i, j
2025-07-02 06:41:16.458                     continue
2025-07-02 06:41:16.458                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.458                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.458                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.458                 # compares by a factor of 3.
2025-07-02 06:41:16.458                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.458                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.458                 # of the computation is cached by cruncher
2025-07-02 06:41:16.458                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.458                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.458                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.458                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.458         if best_ratio < cutoff:
2025-07-02 06:41:16.458             # no non-identical "pretty close" pair
2025-07-02 06:41:16.458             if eqi is None:
2025-07-02 06:41:16.459                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.459                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.459                 return
2025-07-02 06:41:16.459             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.459             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.459         else:
2025-07-02 06:41:16.459             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.459             eqi = None
2025-07-02 06:41:16.459
2025-07-02 06:41:16.459         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.459         # identical
2025-07-02 06:41:16.459
2025-07-02 06:41:16.459         # pump out diffs from before the synch point
2025-07-02 06:41:16.459         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.459
2025-07-02 06:41:16.459         # do intraline marking on the synch pair
2025-07-02 06:41:16.459         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.459         if eqi is None:
2025-07-02 06:41:16.460             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.460             atags = btags = ""
2025-07-02 06:41:16.460             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.460             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.460                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.460                 if tag == 'replace':
2025-07-02 06:41:16.460                     atags += '^' * la
2025-07-02 06:41:16.460                     btags += '^' * lb
2025-07-02 06:41:16.460                 elif tag == 'delete':
2025-07-02 06:41:16.460                     atags += '-' * la
2025-07-02 06:41:16.460                 elif tag == 'insert':
2025-07-02 06:41:16.460                     btags += '+' * lb
2025-07-02 06:41:16.460                 elif tag == 'equal':
2025-07-02 06:41:16.460                     atags += ' ' * la
2025-07-02 06:41:16.460                     btags += ' ' * lb
2025-07-02 06:41:16.460                 else:
2025-07-02 06:41:16.460                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.460             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.461         else:
2025-07-02 06:41:16.461             # the synch pair is identical
2025-07-02 06:41:16.461             yield '  ' + aelt
2025-07-02 06:41:16.461
2025-07-02 06:41:16.461         # pump out diffs from after the synch point
2025-07-02 06:41:16.461 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.461
2025-07-02 06:41:16.461 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.461 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.461
2025-07-02 06:41:16.461 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.461 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.461 alo = 61, ahi = 1101
2025-07-02 06:41:16.461 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.461 blo = 61, bhi = 1101
2025-07-02 06:41:16.461
2025-07-02 06:41:16.461     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.461         g = []
2025-07-02 06:41:16.461         if alo < ahi:
2025-07-02 06:41:16.462             if blo < bhi:
2025-07-02 06:41:16.462                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.462             else:
2025-07-02 06:41:16.462                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.462         elif blo < bhi:
2025-07-02 06:41:16.462             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.462
2025-07-02 06:41:16.462 >       yield from g
2025-07-02 06:41:16.462
2025-07-02 06:41:16.462 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.462 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.462
2025-07-02 06:41:16.462 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.462 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.462 alo = 61, ahi = 1101
2025-07-02 06:41:16.462 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.462 blo = 61, bhi = 1101
2025-07-02 06:41:16.462
2025-07-02 06:41:16.463     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.463         r"""
2025-07-02 06:41:16.463         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.463         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.463         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.463         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.463
2025-07-02 06:41:16.463         Example:
2025-07-02 06:41:16.463
2025-07-02 06:41:16.463         >>> d = Differ()
2025-07-02 06:41:16.463         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.463         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.463         >>> print(''.join(results), end="")
2025-07-02 06:41:16.463         - abcDefghiJkl
2025-07-02 06:41:16.463         + abcdefGhijkl
2025-07-02 06:41:16.463         """
2025-07-02 06:41:16.463
2025-07-02 06:41:16.463         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.464         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.464         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.464         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.464         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.464
2025-07-02 06:41:16.464         # search for the pair that matches best without being identical
2025-07-02 06:41:16.464         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.464         # on junk -- unless we have to)
2025-07-02 06:41:16.464         for j in range(blo, bhi):
2025-07-02 06:41:16.464             bj = b[j]
2025-07-02 06:41:16.464             cruncher.set_seq2(bj)
2025-07-02 06:41:16.464             for i in range(alo, ahi):
2025-07-02 06:41:16.464                 ai = a[i]
2025-07-02 06:41:16.464                 if ai == bj:
2025-07-02 06:41:16.464                     if eqi is None:
2025-07-02 06:41:16.464                         eqi, eqj = i, j
2025-07-02 06:41:16.464                     continue
2025-07-02 06:41:16.464                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.464                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.464                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.465                 # compares by a factor of 3.
2025-07-02 06:41:16.465                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.465                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.465                 # of the computation is cached by cruncher
2025-07-02 06:41:16.465                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.465                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.465                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.465                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.465         if best_ratio < cutoff:
2025-07-02 06:41:16.465             # no non-identical "pretty close" pair
2025-07-02 06:41:16.465             if eqi is None:
2025-07-02 06:41:16.465                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.465                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.465                 return
2025-07-02 06:41:16.465             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.465             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.465         else:
2025-07-02 06:41:16.465             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.465             eqi = None
2025-07-02 06:41:16.466
2025-07-02 06:41:16.466         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.466         # identical
2025-07-02 06:41:16.466
2025-07-02 06:41:16.466         # pump out diffs from before the synch point
2025-07-02 06:41:16.466         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.466
2025-07-02 06:41:16.466         # do intraline marking on the synch pair
2025-07-02 06:41:16.466         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.466         if eqi is None:
2025-07-02 06:41:16.466             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.466             atags = btags = ""
2025-07-02 06:41:16.466             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.466             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.466                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.466                 if tag == 'replace':
2025-07-02 06:41:16.466                     atags += '^' * la
2025-07-02 06:41:16.466                     btags += '^' * lb
2025-07-02 06:41:16.466                 elif tag == 'delete':
2025-07-02 06:41:16.466                     atags += '-' * la
2025-07-02 06:41:16.467                 elif tag == 'insert':
2025-07-02 06:41:16.467                     btags += '+' * lb
2025-07-02 06:41:16.467                 elif tag == 'equal':
2025-07-02 06:41:16.467                     atags += ' ' * la
2025-07-02 06:41:16.467                     btags += ' ' * lb
2025-07-02 06:41:16.467                 else:
2025-07-02 06:41:16.467                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.467             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.467         else:
2025-07-02 06:41:16.467             # the synch pair is identical
2025-07-02 06:41:16.467             yield '  ' + aelt
2025-07-02 06:41:16.467
2025-07-02 06:41:16.467         # pump out diffs from after the synch point
2025-07-02 06:41:16.467 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.467
2025-07-02 06:41:16.467 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.467 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.467
2025-07-02 06:41:16.467 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.468 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.468 alo = 62, ahi = 1101
2025-07-02 06:41:16.468 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.468 blo = 62, bhi = 1101
2025-07-02 06:41:16.468
2025-07-02 06:41:16.468     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.468         g = []
2025-07-02 06:41:16.468         if alo < ahi:
2025-07-02 06:41:16.468             if blo < bhi:
2025-07-02 06:41:16.468                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.468             else:
2025-07-02 06:41:16.468                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.468         elif blo < bhi:
2025-07-02 06:41:16.468             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.468
2025-07-02 06:41:16.468 >       yield from g
2025-07-02 06:41:16.468
2025-07-02 06:41:16.468 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.468 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.469
2025-07-02 06:41:16.469 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.469 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.469 alo = 62, ahi = 1101
2025-07-02 06:41:16.469 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.469 blo = 62, bhi = 1101
2025-07-02 06:41:16.469
2025-07-02 06:41:16.469     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.469         r"""
2025-07-02 06:41:16.469         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.469         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.469         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.469         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.469
2025-07-02 06:41:16.469         Example:
2025-07-02 06:41:16.469
2025-07-02 06:41:16.469         >>> d = Differ()
2025-07-02 06:41:16.469         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.469         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.469         >>> print(''.join(results), end="")
2025-07-02 06:41:16.470         - abcDefghiJkl
2025-07-02 06:41:16.470         + abcdefGhijkl
2025-07-02 06:41:16.470         """
2025-07-02 06:41:16.470
2025-07-02 06:41:16.470         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.470         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.470         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.470         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.470         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.470
2025-07-02 06:41:16.470         # search for the pair that matches best without being identical
2025-07-02 06:41:16.470         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.470         # on junk -- unless we have to)
2025-07-02 06:41:16.470         for j in range(blo, bhi):
2025-07-02 06:41:16.470             bj = b[j]
2025-07-02 06:41:16.470             cruncher.set_seq2(bj)
2025-07-02 06:41:16.470             for i in range(alo, ahi):
2025-07-02 06:41:16.471                 ai = a[i]
2025-07-02 06:41:16.471                 if ai == bj:
2025-07-02 06:41:16.471                     if eqi is None:
2025-07-02 06:41:16.471                         eqi, eqj = i, j
2025-07-02 06:41:16.471                     continue
2025-07-02 06:41:16.471                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.471                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.471                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.471                 # compares by a factor of 3.
2025-07-02 06:41:16.471                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.471                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.471                 # of the computation is cached by cruncher
2025-07-02 06:41:16.471                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.471                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.471                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.471                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.471         if best_ratio < cutoff:
2025-07-02 06:41:16.471             # no non-identical "pretty close" pair
2025-07-02 06:41:16.471             if eqi is None:
2025-07-02 06:41:16.472                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.472                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.472                 return
2025-07-02 06:41:16.472             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.472             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.472         else:
2025-07-02 06:41:16.472             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.472             eqi = None
2025-07-02 06:41:16.472
2025-07-02 06:41:16.472         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.472         # identical
2025-07-02 06:41:16.472
2025-07-02 06:41:16.472         # pump out diffs from before the synch point
2025-07-02 06:41:16.472         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.472
2025-07-02 06:41:16.472         # do intraline marking on the synch pair
2025-07-02 06:41:16.472         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.472         if eqi is None:
2025-07-02 06:41:16.472             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.472             atags = btags = ""
2025-07-02 06:41:16.473             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.473             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.473                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.473                 if tag == 'replace':
2025-07-02 06:41:16.473                     atags += '^' * la
2025-07-02 06:41:16.473                     btags += '^' * lb
2025-07-02 06:41:16.473                 elif tag == 'delete':
2025-07-02 06:41:16.473                     atags += '-' * la
2025-07-02 06:41:16.473                 elif tag == 'insert':
2025-07-02 06:41:16.473                     btags += '+' * lb
2025-07-02 06:41:16.473                 elif tag == 'equal':
2025-07-02 06:41:16.473                     atags += ' ' * la
2025-07-02 06:41:16.473                     btags += ' ' * lb
2025-07-02 06:41:16.473                 else:
2025-07-02 06:41:16.473                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.473             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.473         else:
2025-07-02 06:41:16.473             # the synch pair is identical
2025-07-02 06:41:16.473             yield '  ' + aelt
2025-07-02 06:41:16.473
2025-07-02 06:41:16.474         # pump out diffs from after the synch point
2025-07-02 06:41:16.474 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.474
2025-07-02 06:41:16.474 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.474 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.474
2025-07-02 06:41:16.474 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.474 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.474 alo = 63, ahi = 1101
2025-07-02 06:41:16.474 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.474 blo = 63, bhi = 1101
2025-07-02 06:41:16.474
2025-07-02 06:41:16.474     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.474         g = []
2025-07-02 06:41:16.474         if alo < ahi:
2025-07-02 06:41:16.474             if blo < bhi:
2025-07-02 06:41:16.474                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.474             else:
2025-07-02 06:41:16.474                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.475         elif blo < bhi:
2025-07-02 06:41:16.475             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.475
2025-07-02 06:41:16.475 >       yield from g
2025-07-02 06:41:16.475
2025-07-02 06:41:16.475 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.475 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.475
2025-07-02 06:41:16.475 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.475 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.475 alo = 63, ahi = 1101
2025-07-02 06:41:16.475 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.475 blo = 63, bhi = 1101
2025-07-02 06:41:16.475
2025-07-02 06:41:16.475     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.475         r"""
2025-07-02 06:41:16.475         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.475         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.475         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.476         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.476
2025-07-02 06:41:16.476         Example:
2025-07-02 06:41:16.476
2025-07-02 06:41:16.476         >>> d = Differ()
2025-07-02 06:41:16.476         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.476         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.476         >>> print(''.join(results), end="")
2025-07-02 06:41:16.476         - abcDefghiJkl
2025-07-02 06:41:16.476         + abcdefGhijkl
2025-07-02 06:41:16.476         """
2025-07-02 06:41:16.476
2025-07-02 06:41:16.476         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.476         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.476         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.476         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.476         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.477
2025-07-02 06:41:16.477         # search for the pair that matches best without being identical
2025-07-02 06:41:16.477         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.477         # on junk -- unless we have to)
2025-07-02 06:41:16.477         for j in range(blo, bhi):
2025-07-02 06:41:16.477             bj = b[j]
2025-07-02 06:41:16.477             cruncher.set_seq2(bj)
2025-07-02 06:41:16.477             for i in range(alo, ahi):
2025-07-02 06:41:16.477                 ai = a[i]
2025-07-02 06:41:16.477                 if ai == bj:
2025-07-02 06:41:16.477                     if eqi is None:
2025-07-02 06:41:16.477                         eqi, eqj = i, j
2025-07-02 06:41:16.477                     continue
2025-07-02 06:41:16.477                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.478                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.478                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.478                 # compares by a factor of 3.
2025-07-02 06:41:16.478                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.478                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.478                 # of the computation is cached by cruncher
2025-07-02 06:41:16.478                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.478                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.478                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.478                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.478         if best_ratio < cutoff:
2025-07-02 06:41:16.478             # no non-identical "pretty close" pair
2025-07-02 06:41:16.478             if eqi is None:
2025-07-02 06:41:16.478                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.478                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.478                 return
2025-07-02 06:41:16.478             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.478             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.478         else:
2025-07-02 06:41:16.479             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.479             eqi = None
2025-07-02 06:41:16.479
2025-07-02 06:41:16.479         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.479         # identical
2025-07-02 06:41:16.479
2025-07-02 06:41:16.479         # pump out diffs from before the synch point
2025-07-02 06:41:16.479         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.479
2025-07-02 06:41:16.479         # do intraline marking on the synch pair
2025-07-02 06:41:16.479         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.479         if eqi is None:
2025-07-02 06:41:16.479             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.479             atags = btags = ""
2025-07-02 06:41:16.479             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.479             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.479                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.479                 if tag == 'replace':
2025-07-02 06:41:16.479                     atags += '^' * la
2025-07-02 06:41:16.479                     btags += '^' * lb
2025-07-02 06:41:16.480                 elif tag == 'delete':
2025-07-02 06:41:16.480                     atags += '-' * la
2025-07-02 06:41:16.480                 elif tag == 'insert':
2025-07-02 06:41:16.480                     btags += '+' * lb
2025-07-02 06:41:16.480                 elif tag == 'equal':
2025-07-02 06:41:16.480                     atags += ' ' * la
2025-07-02 06:41:16.480                     btags += ' ' * lb
2025-07-02 06:41:16.480                 else:
2025-07-02 06:41:16.480                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.480             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.480         else:
2025-07-02 06:41:16.480             # the synch pair is identical
2025-07-02 06:41:16.480             yield '  ' + aelt
2025-07-02 06:41:16.480
2025-07-02 06:41:16.480         # pump out diffs from after the synch point
2025-07-02 06:41:16.480 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.480
2025-07-02 06:41:16.480 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.480 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.480
2025-07-02 06:41:16.480 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.481 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.481 alo = 64, ahi = 1101
2025-07-02 06:41:16.481 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.481 blo = 64, bhi = 1101
2025-07-02 06:41:16.481
2025-07-02 06:41:16.481     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.481         g = []
2025-07-02 06:41:16.481         if alo < ahi:
2025-07-02 06:41:16.481             if blo < bhi:
2025-07-02 06:41:16.481                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.481             else:
2025-07-02 06:41:16.481                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.481         elif blo < bhi:
2025-07-02 06:41:16.481             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.481
2025-07-02 06:41:16.481 >       yield from g
2025-07-02 06:41:16.481
2025-07-02 06:41:16.481 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.481 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.481
2025-07-02 06:41:16.482 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.482 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.482 alo = 64, ahi = 1101
2025-07-02 06:41:16.482 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.482 blo = 64, bhi = 1101
2025-07-02 06:41:16.482
2025-07-02 06:41:16.482     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.482         r"""
2025-07-02 06:41:16.482         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.482         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.482         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.482         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.482
2025-07-02 06:41:16.482         Example:
2025-07-02 06:41:16.482
2025-07-02 06:41:16.482         >>> d = Differ()
2025-07-02 06:41:16.482         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.482         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.482         >>> print(''.join(results), end="")
2025-07-02 06:41:16.482         - abcDefghiJkl
2025-07-02 06:41:16.483         + abcdefGhijkl
2025-07-02 06:41:16.483         """
2025-07-02 06:41:16.483
2025-07-02 06:41:16.483         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.483         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.483         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.483         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.483         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.483
2025-07-02 06:41:16.483         # search for the pair that matches best without being identical
2025-07-02 06:41:16.483         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.483         # on junk -- unless we have to)
2025-07-02 06:41:16.483         for j in range(blo, bhi):
2025-07-02 06:41:16.483             bj = b[j]
2025-07-02 06:41:16.483             cruncher.set_seq2(bj)
2025-07-02 06:41:16.483             for i in range(alo, ahi):
2025-07-02 06:41:16.483                 ai = a[i]
2025-07-02 06:41:16.483                 if ai == bj:
2025-07-02 06:41:16.483                     if eqi is None:
2025-07-02 06:41:16.484                         eqi, eqj = i, j
2025-07-02 06:41:16.484                     continue
2025-07-02 06:41:16.484                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.484                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.484                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.484                 # compares by a factor of 3.
2025-07-02 06:41:16.484                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.484                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.484                 # of the computation is cached by cruncher
2025-07-02 06:41:16.484                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.484                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.484                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.484                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.484         if best_ratio < cutoff:
2025-07-02 06:41:16.484             # no non-identical "pretty close" pair
2025-07-02 06:41:16.484             if eqi is None:
2025-07-02 06:41:16.484                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.484                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.484                 return
2025-07-02 06:41:16.484             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.485             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.485         else:
2025-07-02 06:41:16.485             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.485             eqi = None
2025-07-02 06:41:16.485
2025-07-02 06:41:16.485         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.485         # identical
2025-07-02 06:41:16.485
2025-07-02 06:41:16.485         # pump out diffs from before the synch point
2025-07-02 06:41:16.485         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.485
2025-07-02 06:41:16.485         # do intraline marking on the synch pair
2025-07-02 06:41:16.485         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.485         if eqi is None:
2025-07-02 06:41:16.485             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.485             atags = btags = ""
2025-07-02 06:41:16.485             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.485             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.486                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.486                 if tag == 'replace':
2025-07-02 06:41:16.486                     atags += '^' * la
2025-07-02 06:41:16.486                     btags += '^' * lb
2025-07-02 06:41:16.486                 elif tag == 'delete':
2025-07-02 06:41:16.486                     atags += '-' * la
2025-07-02 06:41:16.486                 elif tag == 'insert':
2025-07-02 06:41:16.486                     btags += '+' * lb
2025-07-02 06:41:16.486                 elif tag == 'equal':
2025-07-02 06:41:16.486                     atags += ' ' * la
2025-07-02 06:41:16.486                     btags += ' ' * lb
2025-07-02 06:41:16.486                 else:
2025-07-02 06:41:16.486                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.486             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.486         else:
2025-07-02 06:41:16.486             # the synch pair is identical
2025-07-02 06:41:16.486             yield '  ' + aelt
2025-07-02 06:41:16.486
2025-07-02 06:41:16.486         # pump out diffs from after the synch point
2025-07-02 06:41:16.486 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.487
2025-07-02 06:41:16.487 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.487 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.487
2025-07-02 06:41:16.487 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.487 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.487 alo = 65, ahi = 1101
2025-07-02 06:41:16.487 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.487 blo = 65, bhi = 1101
2025-07-02 06:41:16.487
2025-07-02 06:41:16.487     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.487         g = []
2025-07-02 06:41:16.487         if alo < ahi:
2025-07-02 06:41:16.487             if blo < bhi:
2025-07-02 06:41:16.487                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.487             else:
2025-07-02 06:41:16.487                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.487         elif blo < bhi:
2025-07-02 06:41:16.487             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488 >       yield from g
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.488 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.488 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.488 alo = 65, ahi = 1101
2025-07-02 06:41:16.488 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.488 blo = 65, bhi = 1101
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.488         r"""
2025-07-02 06:41:16.488         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.488         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.488         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.488         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.488
2025-07-02 06:41:16.488         Example:
2025-07-02 06:41:16.488
2025-07-02 06:41:16.489         >>> d = Differ()
2025-07-02 06:41:16.489         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.489         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.489         >>> print(''.join(results), end="")
2025-07-02 06:41:16.489         - abcDefghiJkl
2025-07-02 06:41:16.489         + abcdefGhijkl
2025-07-02 06:41:16.489         """
2025-07-02 06:41:16.489
2025-07-02 06:41:16.489         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.489         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.489         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.489         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.489         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.489
2025-07-02 06:41:16.489         # search for the pair that matches best without being identical
2025-07-02 06:41:16.489         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.489         # on junk -- unless we have to)
2025-07-02 06:41:16.489         for j in range(blo, bhi):
2025-07-02 06:41:16.490             bj = b[j]
2025-07-02 06:41:16.490             cruncher.set_seq2(bj)
2025-07-02 06:41:16.490             for i in range(alo, ahi):
2025-07-02 06:41:16.490                 ai = a[i]
2025-07-02 06:41:16.490                 if ai == bj:
2025-07-02 06:41:16.490                     if eqi is None:
2025-07-02 06:41:16.490                         eqi, eqj = i, j
2025-07-02 06:41:16.490                     continue
2025-07-02 06:41:16.490                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.490                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.490                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.490                 # compares by a factor of 3.
2025-07-02 06:41:16.490                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.490                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.490                 # of the computation is cached by cruncher
2025-07-02 06:41:16.490                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.490                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.490                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.490                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.490         if best_ratio < cutoff:
2025-07-02 06:41:16.490             # no non-identical "pretty close" pair
2025-07-02 06:41:16.491             if eqi is None:
2025-07-02 06:41:16.491                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.491                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.491                 return
2025-07-02 06:41:16.491             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.491             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.491         else:
2025-07-02 06:41:16.491             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.491             eqi = None
2025-07-02 06:41:16.491
2025-07-02 06:41:16.491         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.491         # identical
2025-07-02 06:41:16.491
2025-07-02 06:41:16.491         # pump out diffs from before the synch point
2025-07-02 06:41:16.491         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.491
2025-07-02 06:41:16.491         # do intraline marking on the synch pair
2025-07-02 06:41:16.491         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.492         if eqi is None:
2025-07-02 06:41:16.492             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.492             atags = btags = ""
2025-07-02 06:41:16.492             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.492             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.492                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.492                 if tag == 'replace':
2025-07-02 06:41:16.492                     atags += '^' * la
2025-07-02 06:41:16.492                     btags += '^' * lb
2025-07-02 06:41:16.492                 elif tag == 'delete':
2025-07-02 06:41:16.492                     atags += '-' * la
2025-07-02 06:41:16.492                 elif tag == 'insert':
2025-07-02 06:41:16.492                     btags += '+' * lb
2025-07-02 06:41:16.492                 elif tag == 'equal':
2025-07-02 06:41:16.492                     atags += ' ' * la
2025-07-02 06:41:16.492                     btags += ' ' * lb
2025-07-02 06:41:16.492                 else:
2025-07-02 06:41:16.492                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.492             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.492         else:
2025-07-02 06:41:16.493             # the synch pair is identical
2025-07-02 06:41:16.493             yield '  ' + aelt
2025-07-02 06:41:16.493
2025-07-02 06:41:16.493         # pump out diffs from after the synch point
2025-07-02 06:41:16.493 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.493
2025-07-02 06:41:16.493 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.493 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.493
2025-07-02 06:41:16.493 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.493 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.493 alo = 66, ahi = 1101
2025-07-02 06:41:16.493 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.493 blo = 66, bhi = 1101
2025-07-02 06:41:16.493
2025-07-02 06:41:16.493     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.493         g = []
2025-07-02 06:41:16.493         if alo < ahi:
2025-07-02 06:41:16.493             if blo < bhi:
2025-07-02 06:41:16.493                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.494             else:
2025-07-02 06:41:16.494                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.494         elif blo < bhi:
2025-07-02 06:41:16.494             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.494
2025-07-02 06:41:16.494 >       yield from g
2025-07-02 06:41:16.494
2025-07-02 06:41:16.494 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.494 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.494
2025-07-02 06:41:16.494 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.494 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.494 alo = 66, ahi = 1101
2025-07-02 06:41:16.494 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.494 blo = 66, bhi = 1101
2025-07-02 06:41:16.494
2025-07-02 06:41:16.494     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.494         r"""
2025-07-02 06:41:16.495         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.495         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.495         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.495         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.495
2025-07-02 06:41:16.495         Example:
2025-07-02 06:41:16.495
2025-07-02 06:41:16.495         >>> d = Differ()
2025-07-02 06:41:16.495         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.495         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.495         >>> print(''.join(results), end="")
2025-07-02 06:41:16.495         - abcDefghiJkl
2025-07-02 06:41:16.495         + abcdefGhijkl
2025-07-02 06:41:16.495         """
2025-07-02 06:41:16.495
2025-07-02 06:41:16.495         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.495         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.495         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.496         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.496         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.496
2025-07-02 06:41:16.496         # search for the pair that matches best without being identical
2025-07-02 06:41:16.496         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.496         # on junk -- unless we have to)
2025-07-02 06:41:16.496         for j in range(blo, bhi):
2025-07-02 06:41:16.496             bj = b[j]
2025-07-02 06:41:16.496             cruncher.set_seq2(bj)
2025-07-02 06:41:16.496             for i in range(alo, ahi):
2025-07-02 06:41:16.496                 ai = a[i]
2025-07-02 06:41:16.496                 if ai == bj:
2025-07-02 06:41:16.496                     if eqi is None:
2025-07-02 06:41:16.496                         eqi, eqj = i, j
2025-07-02 06:41:16.496                     continue
2025-07-02 06:41:16.496                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.496                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.496                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.496                 # compares by a factor of 3.
2025-07-02 06:41:16.496                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.497                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.497                 # of the computation is cached by cruncher
2025-07-02 06:41:16.497                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.497                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.497                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.497                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.497         if best_ratio < cutoff:
2025-07-02 06:41:16.497             # no non-identical "pretty close" pair
2025-07-02 06:41:16.497             if eqi is None:
2025-07-02 06:41:16.497                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.497                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.497                 return
2025-07-02 06:41:16.497             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.497             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.497         else:
2025-07-02 06:41:16.497             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.497             eqi = None
2025-07-02 06:41:16.497
2025-07-02 06:41:16.497         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.497         # identical
2025-07-02 06:41:16.498
2025-07-02 06:41:16.498         # pump out diffs from before the synch point
2025-07-02 06:41:16.498         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.498
2025-07-02 06:41:16.498         # do intraline marking on the synch pair
2025-07-02 06:41:16.498         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.498         if eqi is None:
2025-07-02 06:41:16.498             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.498             atags = btags = ""
2025-07-02 06:41:16.498             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.498             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.498                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.498                 if tag == 'replace':
2025-07-02 06:41:16.498                     atags += '^' * la
2025-07-02 06:41:16.498                     btags += '^' * lb
2025-07-02 06:41:16.498                 elif tag == 'delete':
2025-07-02 06:41:16.498                     atags += '-' * la
2025-07-02 06:41:16.498                 elif tag == 'insert':
2025-07-02 06:41:16.498                     btags += '+' * lb
2025-07-02 06:41:16.498                 elif tag == 'equal':
2025-07-02 06:41:16.498                     atags += ' ' * la
2025-07-02 06:41:16.499                     btags += ' ' * lb
2025-07-02 06:41:16.499                 else:
2025-07-02 06:41:16.499                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.499             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.499         else:
2025-07-02 06:41:16.499             # the synch pair is identical
2025-07-02 06:41:16.499             yield '  ' + aelt
2025-07-02 06:41:16.499
2025-07-02 06:41:16.499         # pump out diffs from after the synch point
2025-07-02 06:41:16.499 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.499
2025-07-02 06:41:16.499 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.499 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.499
2025-07-02 06:41:16.499 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.499 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.499 alo = 67, ahi = 1101
2025-07-02 06:41:16.499 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.499 blo = 67, bhi = 1101
2025-07-02 06:41:16.499
2025-07-02 06:41:16.500     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.500         g = []
2025-07-02 06:41:16.500         if alo < ahi:
2025-07-02 06:41:16.500             if blo < bhi:
2025-07-02 06:41:16.500                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.500             else:
2025-07-02 06:41:16.500                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.500         elif blo < bhi:
2025-07-02 06:41:16.500             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.500
2025-07-02 06:41:16.500 >       yield from g
2025-07-02 06:41:16.500
2025-07-02 06:41:16.500 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.500 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.500
2025-07-02 06:41:16.500 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.500 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.500 alo = 67, ahi = 1101
2025-07-02 06:41:16.500 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.500 blo = 67, bhi = 1101
2025-07-02 06:41:16.501
2025-07-02 06:41:16.501     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.501         r"""
2025-07-02 06:41:16.501         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.501         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.501         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.501         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.501
2025-07-02 06:41:16.501         Example:
2025-07-02 06:41:16.501
2025-07-02 06:41:16.501         >>> d = Differ()
2025-07-02 06:41:16.501         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.501         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.501         >>> print(''.join(results), end="")
2025-07-02 06:41:16.501         - abcDefghiJkl
2025-07-02 06:41:16.501         + abcdefGhijkl
2025-07-02 06:41:16.501         """
2025-07-02 06:41:16.501
2025-07-02 06:41:16.501         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.502         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.502         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.502         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.502         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.502
2025-07-02 06:41:16.502         # search for the pair that matches best without being identical
2025-07-02 06:41:16.502         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.502         # on junk -- unless we have to)
2025-07-02 06:41:16.502         for j in range(blo, bhi):
2025-07-02 06:41:16.502             bj = b[j]
2025-07-02 06:41:16.502             cruncher.set_seq2(bj)
2025-07-02 06:41:16.502             for i in range(alo, ahi):
2025-07-02 06:41:16.502                 ai = a[i]
2025-07-02 06:41:16.502                 if ai == bj:
2025-07-02 06:41:16.502                     if eqi is None:
2025-07-02 06:41:16.502                         eqi, eqj = i, j
2025-07-02 06:41:16.502                     continue
2025-07-02 06:41:16.502                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.502                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.502                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.503                 # compares by a factor of 3.
2025-07-02 06:41:16.503                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.503                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.503                 # of the computation is cached by cruncher
2025-07-02 06:41:16.503                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.503                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.503                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.503                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.503         if best_ratio < cutoff:
2025-07-02 06:41:16.503             # no non-identical "pretty close" pair
2025-07-02 06:41:16.503             if eqi is None:
2025-07-02 06:41:16.503                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.503                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.503                 return
2025-07-02 06:41:16.503             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.503             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.503         else:
2025-07-02 06:41:16.503             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.503             eqi = None
2025-07-02 06:41:16.504
2025-07-02 06:41:16.504         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.504         # identical
2025-07-02 06:41:16.504
2025-07-02 06:41:16.504         # pump out diffs from before the synch point
2025-07-02 06:41:16.504         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.504
2025-07-02 06:41:16.504         # do intraline marking on the synch pair
2025-07-02 06:41:16.504         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.504         if eqi is None:
2025-07-02 06:41:16.504             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.504             atags = btags = ""
2025-07-02 06:41:16.504             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.504             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.504                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.504                 if tag == 'replace':
2025-07-02 06:41:16.504                     atags += '^' * la
2025-07-02 06:41:16.504                     btags += '^' * lb
2025-07-02 06:41:16.504                 elif tag == 'delete':
2025-07-02 06:41:16.504                     atags += '-' * la
2025-07-02 06:41:16.505                 elif tag == 'insert':
2025-07-02 06:41:16.505                     btags += '+' * lb
2025-07-02 06:41:16.505                 elif tag == 'equal':
2025-07-02 06:41:16.505                     atags += ' ' * la
2025-07-02 06:41:16.505                     btags += ' ' * lb
2025-07-02 06:41:16.505                 else:
2025-07-02 06:41:16.505                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.505             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.505         else:
2025-07-02 06:41:16.505             # the synch pair is identical
2025-07-02 06:41:16.505             yield '  ' + aelt
2025-07-02 06:41:16.505
2025-07-02 06:41:16.505         # pump out diffs from after the synch point
2025-07-02 06:41:16.505 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.505
2025-07-02 06:41:16.505 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.505 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.505
2025-07-02 06:41:16.505 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.505 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.506 alo = 70, ahi = 1101
2025-07-02 06:41:16.506 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.506 blo = 70, bhi = 1101
2025-07-02 06:41:16.506
2025-07-02 06:41:16.506     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.506         g = []
2025-07-02 06:41:16.506         if alo < ahi:
2025-07-02 06:41:16.506             if blo < bhi:
2025-07-02 06:41:16.506                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.506             else:
2025-07-02 06:41:16.506                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.506         elif blo < bhi:
2025-07-02 06:41:16.506             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.506
2025-07-02 06:41:16.506 >       yield from g
2025-07-02 06:41:16.506
2025-07-02 06:41:16.506 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.506 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.506
2025-07-02 06:41:16.506 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.506 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.507 alo = 70, ahi = 1101
2025-07-02 06:41:16.507 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.507 blo = 70, bhi = 1101
2025-07-02 06:41:16.507
2025-07-02 06:41:16.507     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.507         r"""
2025-07-02 06:41:16.507         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.507         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.507         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.507         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.507
2025-07-02 06:41:16.507         Example:
2025-07-02 06:41:16.507
2025-07-02 06:41:16.507         >>> d = Differ()
2025-07-02 06:41:16.507         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.507         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.507         >>> print(''.join(results), end="")
2025-07-02 06:41:16.507         - abcDefghiJkl
2025-07-02 06:41:16.508         + abcdefGhijkl
2025-07-02 06:41:16.508         """
2025-07-02 06:41:16.508
2025-07-02 06:41:16.508         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.508         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.508         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.508         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.508         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.508
2025-07-02 06:41:16.508         # search for the pair that matches best without being identical
2025-07-02 06:41:16.508         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.508         # on junk -- unless we have to)
2025-07-02 06:41:16.508         for j in range(blo, bhi):
2025-07-02 06:41:16.508             bj = b[j]
2025-07-02 06:41:16.508             cruncher.set_seq2(bj)
2025-07-02 06:41:16.508             for i in range(alo, ahi):
2025-07-02 06:41:16.508                 ai = a[i]
2025-07-02 06:41:16.508                 if ai == bj:
2025-07-02 06:41:16.508                     if eqi is None:
2025-07-02 06:41:16.509                         eqi, eqj = i, j
2025-07-02 06:41:16.509                     continue
2025-07-02 06:41:16.509                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.509                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.509                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.509                 # compares by a factor of 3.
2025-07-02 06:41:16.509                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.509                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.509                 # of the computation is cached by cruncher
2025-07-02 06:41:16.509                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.509                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.509                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.509                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.509         if best_ratio < cutoff:
2025-07-02 06:41:16.509             # no non-identical "pretty close" pair
2025-07-02 06:41:16.509             if eqi is None:
2025-07-02 06:41:16.509                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.509                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.509                 return
2025-07-02 06:41:16.509             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.510             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.510         else:
2025-07-02 06:41:16.510             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.510             eqi = None
2025-07-02 06:41:16.510
2025-07-02 06:41:16.510         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.510         # identical
2025-07-02 06:41:16.510
2025-07-02 06:41:16.510         # pump out diffs from before the synch point
2025-07-02 06:41:16.510         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.510
2025-07-02 06:41:16.510         # do intraline marking on the synch pair
2025-07-02 06:41:16.510         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.510         if eqi is None:
2025-07-02 06:41:16.510             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.510             atags = btags = ""
2025-07-02 06:41:16.510             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.510             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.510                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.510                 if tag == 'replace':
2025-07-02 06:41:16.510                     atags += '^' * la
2025-07-02 06:41:16.511                     btags += '^' * lb
2025-07-02 06:41:16.511                 elif tag == 'delete':
2025-07-02 06:41:16.511                     atags += '-' * la
2025-07-02 06:41:16.511                 elif tag == 'insert':
2025-07-02 06:41:16.511                     btags += '+' * lb
2025-07-02 06:41:16.511                 elif tag == 'equal':
2025-07-02 06:41:16.511                     atags += ' ' * la
2025-07-02 06:41:16.511                     btags += ' ' * lb
2025-07-02 06:41:16.511                 else:
2025-07-02 06:41:16.511                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.511             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.511         else:
2025-07-02 06:41:16.511             # the synch pair is identical
2025-07-02 06:41:16.511             yield '  ' + aelt
2025-07-02 06:41:16.511
2025-07-02 06:41:16.511         # pump out diffs from after the synch point
2025-07-02 06:41:16.511 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.511
2025-07-02 06:41:16.511 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.511 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.512
2025-07-02 06:41:16.512 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.512 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.512 alo = 71, ahi = 1101
2025-07-02 06:41:16.512 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.512 blo = 71, bhi = 1101
2025-07-02 06:41:16.512
2025-07-02 06:41:16.512     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.512         g = []
2025-07-02 06:41:16.512         if alo < ahi:
2025-07-02 06:41:16.512             if blo < bhi:
2025-07-02 06:41:16.512                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.512             else:
2025-07-02 06:41:16.512                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.512         elif blo < bhi:
2025-07-02 06:41:16.512             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.512
2025-07-02 06:41:16.512 >       yield from g
2025-07-02 06:41:16.512
2025-07-02 06:41:16.513 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.513 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.513
2025-07-02 06:41:16.513 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.513 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.513 alo = 71, ahi = 1101
2025-07-02 06:41:16.513 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.513 blo = 71, bhi = 1101
2025-07-02 06:41:16.513
2025-07-02 06:41:16.513     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.513         r"""
2025-07-02 06:41:16.513         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.513         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.513         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.513         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.513
2025-07-02 06:41:16.513         Example:
2025-07-02 06:41:16.513
2025-07-02 06:41:16.513         >>> d = Differ()
2025-07-02 06:41:16.513         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.514         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.514         >>> print(''.join(results), end="")
2025-07-02 06:41:16.514         - abcDefghiJkl
2025-07-02 06:41:16.514         + abcdefGhijkl
2025-07-02 06:41:16.514         """
2025-07-02 06:41:16.514
2025-07-02 06:41:16.514         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.514         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.514         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.514         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.514         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.514
2025-07-02 06:41:16.514         # search for the pair that matches best without being identical
2025-07-02 06:41:16.514         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.514         # on junk -- unless we have to)
2025-07-02 06:41:16.514         for j in range(blo, bhi):
2025-07-02 06:41:16.514             bj = b[j]
2025-07-02 06:41:16.514             cruncher.set_seq2(bj)
2025-07-02 06:41:16.515             for i in range(alo, ahi):
2025-07-02 06:41:16.515                 ai = a[i]
2025-07-02 06:41:16.515                 if ai == bj:
2025-07-02 06:41:16.515                     if eqi is None:
2025-07-02 06:41:16.515                         eqi, eqj = i, j
2025-07-02 06:41:16.515                     continue
2025-07-02 06:41:16.515                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.515                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.515                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.515                 # compares by a factor of 3.
2025-07-02 06:41:16.515                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.515                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.515                 # of the computation is cached by cruncher
2025-07-02 06:41:16.515                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.515                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.515                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.515                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.515         if best_ratio < cutoff:
2025-07-02 06:41:16.515             # no non-identical "pretty close" pair
2025-07-02 06:41:16.515             if eqi is None:
2025-07-02 06:41:16.515                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.516                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.516                 return
2025-07-02 06:41:16.516             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.516             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.516         else:
2025-07-02 06:41:16.516             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.516             eqi = None
2025-07-02 06:41:16.516
2025-07-02 06:41:16.516         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.516         # identical
2025-07-02 06:41:16.516
2025-07-02 06:41:16.516         # pump out diffs from before the synch point
2025-07-02 06:41:16.516         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.516
2025-07-02 06:41:16.516         # do intraline marking on the synch pair
2025-07-02 06:41:16.516         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.516         if eqi is None:
2025-07-02 06:41:16.516             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.516             atags = btags = ""
2025-07-02 06:41:16.516             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.517             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.517                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.517                 if tag == 'replace':
2025-07-02 06:41:16.517                     atags += '^' * la
2025-07-02 06:41:16.517                     btags += '^' * lb
2025-07-02 06:41:16.517                 elif tag == 'delete':
2025-07-02 06:41:16.517                     atags += '-' * la
2025-07-02 06:41:16.517                 elif tag == 'insert':
2025-07-02 06:41:16.517                     btags += '+' * lb
2025-07-02 06:41:16.517                 elif tag == 'equal':
2025-07-02 06:41:16.517                     atags += ' ' * la
2025-07-02 06:41:16.517                     btags += ' ' * lb
2025-07-02 06:41:16.517                 else:
2025-07-02 06:41:16.517                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.517             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.517         else:
2025-07-02 06:41:16.517             # the synch pair is identical
2025-07-02 06:41:16.517             yield '  ' + aelt
2025-07-02 06:41:16.518
2025-07-02 06:41:16.518         # pump out diffs from after the synch point
2025-07-02 06:41:16.518 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.518
2025-07-02 06:41:16.518 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.518 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.518
2025-07-02 06:41:16.518 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.518 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.518 alo = 72, ahi = 1101
2025-07-02 06:41:16.518 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.518 blo = 72, bhi = 1101
2025-07-02 06:41:16.518
2025-07-02 06:41:16.518     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.518         g = []
2025-07-02 06:41:16.518         if alo < ahi:
2025-07-02 06:41:16.518             if blo < bhi:
2025-07-02 06:41:16.518                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.518             else:
2025-07-02 06:41:16.518                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.519         elif blo < bhi:
2025-07-02 06:41:16.519             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.519
2025-07-02 06:41:16.519 >       yield from g
2025-07-02 06:41:16.519
2025-07-02 06:41:16.519 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.519 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.519
2025-07-02 06:41:16.519 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.519 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.519 alo = 72, ahi = 1101
2025-07-02 06:41:16.519 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.519 blo = 72, bhi = 1101
2025-07-02 06:41:16.519
2025-07-02 06:41:16.519     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.519         r"""
2025-07-02 06:41:16.519         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.519         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.519         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.519         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.519
2025-07-02 06:41:16.520         Example:
2025-07-02 06:41:16.520
2025-07-02 06:41:16.520         >>> d = Differ()
2025-07-02 06:41:16.520         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.520         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.520         >>> print(''.join(results), end="")
2025-07-02 06:41:16.520         - abcDefghiJkl
2025-07-02 06:41:16.520         + abcdefGhijkl
2025-07-02 06:41:16.520         """
2025-07-02 06:41:16.520
2025-07-02 06:41:16.520         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.520         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.520         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.520         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.520         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.520
2025-07-02 06:41:16.520         # search for the pair that matches best without being identical
2025-07-02 06:41:16.521         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.521         # on junk -- unless we have to)
2025-07-02 06:41:16.521         for j in range(blo, bhi):
2025-07-02 06:41:16.521             bj = b[j]
2025-07-02 06:41:16.521             cruncher.set_seq2(bj)
2025-07-02 06:41:16.521             for i in range(alo, ahi):
2025-07-02 06:41:16.521                 ai = a[i]
2025-07-02 06:41:16.521                 if ai == bj:
2025-07-02 06:41:16.521                     if eqi is None:
2025-07-02 06:41:16.521                         eqi, eqj = i, j
2025-07-02 06:41:16.521                     continue
2025-07-02 06:41:16.521                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.521                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.521                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.521                 # compares by a factor of 3.
2025-07-02 06:41:16.521                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.521                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.521                 # of the computation is cached by cruncher
2025-07-02 06:41:16.521                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.522                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.522                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.522                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.522         if best_ratio < cutoff:
2025-07-02 06:41:16.522             # no non-identical "pretty close" pair
2025-07-02 06:41:16.522             if eqi is None:
2025-07-02 06:41:16.522                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.522                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.522                 return
2025-07-02 06:41:16.522             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.522             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.522         else:
2025-07-02 06:41:16.522             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.522             eqi = None
2025-07-02 06:41:16.522
2025-07-02 06:41:16.522         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.522         # identical
2025-07-02 06:41:16.522
2025-07-02 06:41:16.522         # pump out diffs from before the synch point
2025-07-02 06:41:16.522         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.522
2025-07-02 06:41:16.523         # do intraline marking on the synch pair
2025-07-02 06:41:16.523         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.523         if eqi is None:
2025-07-02 06:41:16.523             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.523             atags = btags = ""
2025-07-02 06:41:16.523             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.523             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.523                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.523                 if tag == 'replace':
2025-07-02 06:41:16.523                     atags += '^' * la
2025-07-02 06:41:16.523                     btags += '^' * lb
2025-07-02 06:41:16.523                 elif tag == 'delete':
2025-07-02 06:41:16.523                     atags += '-' * la
2025-07-02 06:41:16.523                 elif tag == 'insert':
2025-07-02 06:41:16.523                     btags += '+' * lb
2025-07-02 06:41:16.523                 elif tag == 'equal':
2025-07-02 06:41:16.523                     atags += ' ' * la
2025-07-02 06:41:16.523                     btags += ' ' * lb
2025-07-02 06:41:16.524                 else:
2025-07-02 06:41:16.524                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.524             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.524         else:
2025-07-02 06:41:16.524             # the synch pair is identical
2025-07-02 06:41:16.524             yield '  ' + aelt
2025-07-02 06:41:16.524
2025-07-02 06:41:16.524         # pump out diffs from after the synch point
2025-07-02 06:41:16.524 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.524
2025-07-02 06:41:16.524 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.524 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.524
2025-07-02 06:41:16.524 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.524 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.524 alo = 73, ahi = 1101
2025-07-02 06:41:16.524 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.524 blo = 73, bhi = 1101
2025-07-02 06:41:16.524
2025-07-02 06:41:16.525     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.525         g = []
2025-07-02 06:41:16.525         if alo < ahi:
2025-07-02 06:41:16.525             if blo < bhi:
2025-07-02 06:41:16.525                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.525             else:
2025-07-02 06:41:16.525                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.525         elif blo < bhi:
2025-07-02 06:41:16.525             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.525
2025-07-02 06:41:16.525 >       yield from g
2025-07-02 06:41:16.525
2025-07-02 06:41:16.525 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.525 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.525
2025-07-02 06:41:16.525 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.525 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.525 alo = 73, ahi = 1101
2025-07-02 06:41:16.525 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.526 blo = 73, bhi = 1101
2025-07-02 06:41:16.526
2025-07-02 06:41:16.526     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.526         r"""
2025-07-02 06:41:16.526         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.526         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.526         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.526         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.526
2025-07-02 06:41:16.526         Example:
2025-07-02 06:41:16.526
2025-07-02 06:41:16.526         >>> d = Differ()
2025-07-02 06:41:16.526         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.527         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.527         >>> print(''.join(results), end="")
2025-07-02 06:41:16.527         - abcDefghiJkl
2025-07-02 06:41:16.527         + abcdefGhijkl
2025-07-02 06:41:16.527         """
2025-07-02 06:41:16.527
2025-07-02 06:41:16.527         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.527         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.527         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.527         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.527         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.527
2025-07-02 06:41:16.527         # search for the pair that matches best without being identical
2025-07-02 06:41:16.527         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.527         # on junk -- unless we have to)
2025-07-02 06:41:16.527         for j in range(blo, bhi):
2025-07-02 06:41:16.527             bj = b[j]
2025-07-02 06:41:16.528             cruncher.set_seq2(bj)
2025-07-02 06:41:16.528             for i in range(alo, ahi):
2025-07-02 06:41:16.528                 ai = a[i]
2025-07-02 06:41:16.528                 if ai == bj:
2025-07-02 06:41:16.528                     if eqi is None:
2025-07-02 06:41:16.528                         eqi, eqj = i, j
2025-07-02 06:41:16.528                     continue
2025-07-02 06:41:16.528                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.528                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.528                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.528                 # compares by a factor of 3.
2025-07-02 06:41:16.528                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.528                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.528                 # of the computation is cached by cruncher
2025-07-02 06:41:16.528                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.528                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.528                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.528                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.528         if best_ratio < cutoff:
2025-07-02 06:41:16.528             # no non-identical "pretty close" pair
2025-07-02 06:41:16.529             if eqi is None:
2025-07-02 06:41:16.529                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.529                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.529                 return
2025-07-02 06:41:16.529             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.529             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.529         else:
2025-07-02 06:41:16.529             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.529             eqi = None
2025-07-02 06:41:16.529
2025-07-02 06:41:16.529         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.529         # identical
2025-07-02 06:41:16.529
2025-07-02 06:41:16.529         # pump out diffs from before the synch point
2025-07-02 06:41:16.529         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.529
2025-07-02 06:41:16.529         # do intraline marking on the synch pair
2025-07-02 06:41:16.529         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.530         if eqi is None:
2025-07-02 06:41:16.530             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.530             atags = btags = ""
2025-07-02 06:41:16.530             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.530             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.530                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.530                 if tag == 'replace':
2025-07-02 06:41:16.530                     atags += '^' * la
2025-07-02 06:41:16.530                     btags += '^' * lb
2025-07-02 06:41:16.530                 elif tag == 'delete':
2025-07-02 06:41:16.530                     atags += '-' * la
2025-07-02 06:41:16.530                 elif tag == 'insert':
2025-07-02 06:41:16.530                     btags += '+' * lb
2025-07-02 06:41:16.530                 elif tag == 'equal':
2025-07-02 06:41:16.530                     atags += ' ' * la
2025-07-02 06:41:16.530                     btags += ' ' * lb
2025-07-02 06:41:16.530                 else:
2025-07-02 06:41:16.530                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.530             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.530         else:
2025-07-02 06:41:16.530             # the synch pair is identical
2025-07-02 06:41:16.530             yield '  ' + aelt
2025-07-02 06:41:16.531
2025-07-02 06:41:16.531         # pump out diffs from after the synch point
2025-07-02 06:41:16.531 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.531
2025-07-02 06:41:16.531 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.531 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.531
2025-07-02 06:41:16.531 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.531 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.531 alo = 74, ahi = 1101
2025-07-02 06:41:16.531 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.531 blo = 74, bhi = 1101
2025-07-02 06:41:16.531
2025-07-02 06:41:16.531     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.531         g = []
2025-07-02 06:41:16.531         if alo < ahi:
2025-07-02 06:41:16.531             if blo < bhi:
2025-07-02 06:41:16.531                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.531             else:
2025-07-02 06:41:16.531                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.532         elif blo < bhi:
2025-07-02 06:41:16.532             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.532
2025-07-02 06:41:16.532 >       yield from g
2025-07-02 06:41:16.532
2025-07-02 06:41:16.532 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.532 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.532
2025-07-02 06:41:16.532 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.532 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.532 alo = 74, ahi = 1101
2025-07-02 06:41:16.532 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.532 blo = 74, bhi = 1101
2025-07-02 06:41:16.532
2025-07-02 06:41:16.532     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.532         r"""
2025-07-02 06:41:16.532         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.532         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.532         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.532         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.533
2025-07-02 06:41:16.533         Example:
2025-07-02 06:41:16.533
2025-07-02 06:41:16.533         >>> d = Differ()
2025-07-02 06:41:16.533         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.533         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.533         >>> print(''.join(results), end="")
2025-07-02 06:41:16.533         - abcDefghiJkl
2025-07-02 06:41:16.533         + abcdefGhijkl
2025-07-02 06:41:16.533         """
2025-07-02 06:41:16.533
2025-07-02 06:41:16.533         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.533         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.533         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.533         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.533         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.533
2025-07-02 06:41:16.533         # search for the pair that matches best without being identical
2025-07-02 06:41:16.533         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.534         # on junk -- unless we have to)
2025-07-02 06:41:16.534         for j in range(blo, bhi):
2025-07-02 06:41:16.534             bj = b[j]
2025-07-02 06:41:16.534             cruncher.set_seq2(bj)
2025-07-02 06:41:16.534             for i in range(alo, ahi):
2025-07-02 06:41:16.534                 ai = a[i]
2025-07-02 06:41:16.534                 if ai == bj:
2025-07-02 06:41:16.534                     if eqi is None:
2025-07-02 06:41:16.534                         eqi, eqj = i, j
2025-07-02 06:41:16.534                     continue
2025-07-02 06:41:16.534                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.534                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.534                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.534                 # compares by a factor of 3.
2025-07-02 06:41:16.534                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.534                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.534                 # of the computation is cached by cruncher
2025-07-02 06:41:16.534                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.534                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.534                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.535                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.535         if best_ratio < cutoff:
2025-07-02 06:41:16.535             # no non-identical "pretty close" pair
2025-07-02 06:41:16.535             if eqi is None:
2025-07-02 06:41:16.535                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.535                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.535                 return
2025-07-02 06:41:16.535             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.535             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.535         else:
2025-07-02 06:41:16.535             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.535             eqi = None
2025-07-02 06:41:16.535
2025-07-02 06:41:16.535         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.535         # identical
2025-07-02 06:41:16.535
2025-07-02 06:41:16.535         # pump out diffs from before the synch point
2025-07-02 06:41:16.535         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.535
2025-07-02 06:41:16.536         # do intraline marking on the synch pair
2025-07-02 06:41:16.536         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.536         if eqi is None:
2025-07-02 06:41:16.536             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.536             atags = btags = ""
2025-07-02 06:41:16.536             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.536             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.536                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.536                 if tag == 'replace':
2025-07-02 06:41:16.536                     atags += '^' * la
2025-07-02 06:41:16.536                     btags += '^' * lb
2025-07-02 06:41:16.536                 elif tag == 'delete':
2025-07-02 06:41:16.536                     atags += '-' * la
2025-07-02 06:41:16.536                 elif tag == 'insert':
2025-07-02 06:41:16.536                     btags += '+' * lb
2025-07-02 06:41:16.536                 elif tag == 'equal':
2025-07-02 06:41:16.536                     atags += ' ' * la
2025-07-02 06:41:16.536                     btags += ' ' * lb
2025-07-02 06:41:16.536                 else:
2025-07-02 06:41:16.537                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.537             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.537         else:
2025-07-02 06:41:16.537             # the synch pair is identical
2025-07-02 06:41:16.537             yield '  ' + aelt
2025-07-02 06:41:16.537
2025-07-02 06:41:16.537         # pump out diffs from after the synch point
2025-07-02 06:41:16.537 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.537
2025-07-02 06:41:16.537 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.537 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.537
2025-07-02 06:41:16.537 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.537 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.537 alo = 75, ahi = 1101
2025-07-02 06:41:16.537 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.537 blo = 75, bhi = 1101
2025-07-02 06:41:16.537
2025-07-02 06:41:16.537     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.537         g = []
2025-07-02 06:41:16.538         if alo < ahi:
2025-07-02 06:41:16.538             if blo < bhi:
2025-07-02 06:41:16.538                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.538             else:
2025-07-02 06:41:16.538                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.538         elif blo < bhi:
2025-07-02 06:41:16.538             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.538
2025-07-02 06:41:16.538 >       yield from g
2025-07-02 06:41:16.538
2025-07-02 06:41:16.538 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.538 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.538
2025-07-02 06:41:16.538 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.538 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.538 alo = 75, ahi = 1101
2025-07-02 06:41:16.538 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.539 blo = 75, bhi = 1101
2025-07-02 06:41:16.539
2025-07-02 06:41:16.539     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.539         r"""
2025-07-02 06:41:16.539         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.539         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.539         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.539         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.539
2025-07-02 06:41:16.539         Example:
2025-07-02 06:41:16.539
2025-07-02 06:41:16.539         >>> d = Differ()
2025-07-02 06:41:16.539         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.539         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.539         >>> print(''.join(results), end="")
2025-07-02 06:41:16.539         - abcDefghiJkl
2025-07-02 06:41:16.539         + abcdefGhijkl
2025-07-02 06:41:16.540         """
2025-07-02 06:41:16.540
2025-07-02 06:41:16.540         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.540         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.540         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.540         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.540         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.540
2025-07-02 06:41:16.540         # search for the pair that matches best without being identical
2025-07-02 06:41:16.540         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.540         # on junk -- unless we have to)
2025-07-02 06:41:16.540         for j in range(blo, bhi):
2025-07-02 06:41:16.540             bj = b[j]
2025-07-02 06:41:16.540             cruncher.set_seq2(bj)
2025-07-02 06:41:16.540             for i in range(alo, ahi):
2025-07-02 06:41:16.540                 ai = a[i]
2025-07-02 06:41:16.540                 if ai == bj:
2025-07-02 06:41:16.540                     if eqi is None:
2025-07-02 06:41:16.540                         eqi, eqj = i, j
2025-07-02 06:41:16.540                     continue
2025-07-02 06:41:16.541                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.541                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.541                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.541                 # compares by a factor of 3.
2025-07-02 06:41:16.541                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.541                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.541                 # of the computation is cached by cruncher
2025-07-02 06:41:16.541                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.541                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.541                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.541                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.541         if best_ratio < cutoff:
2025-07-02 06:41:16.541             # no non-identical "pretty close" pair
2025-07-02 06:41:16.541             if eqi is None:
2025-07-02 06:41:16.541                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.541                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.541                 return
2025-07-02 06:41:16.541             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.541             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.541         else:
2025-07-02 06:41:16.542             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.542             eqi = None
2025-07-02 06:41:16.542
2025-07-02 06:41:16.542         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.542         # identical
2025-07-02 06:41:16.542
2025-07-02 06:41:16.542         # pump out diffs from before the synch point
2025-07-02 06:41:16.542         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.542
2025-07-02 06:41:16.542         # do intraline marking on the synch pair
2025-07-02 06:41:16.542         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.542         if eqi is None:
2025-07-02 06:41:16.542             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.542             atags = btags = ""
2025-07-02 06:41:16.542             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.542             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.542                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.542                 if tag == 'replace':
2025-07-02 06:41:16.542                     atags += '^' * la
2025-07-02 06:41:16.542                     btags += '^' * lb
2025-07-02 06:41:16.542                 elif tag == 'delete':
2025-07-02 06:41:16.543                     atags += '-' * la
2025-07-02 06:41:16.543                 elif tag == 'insert':
2025-07-02 06:41:16.543                     btags += '+' * lb
2025-07-02 06:41:16.543                 elif tag == 'equal':
2025-07-02 06:41:16.543                     atags += ' ' * la
2025-07-02 06:41:16.543                     btags += ' ' * lb
2025-07-02 06:41:16.543                 else:
2025-07-02 06:41:16.543                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.543             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.543         else:
2025-07-02 06:41:16.543             # the synch pair is identical
2025-07-02 06:41:16.543             yield '  ' + aelt
2025-07-02 06:41:16.543
2025-07-02 06:41:16.543         # pump out diffs from after the synch point
2025-07-02 06:41:16.543 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.543
2025-07-02 06:41:16.543 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.543 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.543
2025-07-02 06:41:16.543 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.544 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.544 alo = 76, ahi = 1101
2025-07-02 06:41:16.544 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.544 blo = 76, bhi = 1101
2025-07-02 06:41:16.544
2025-07-02 06:41:16.544     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.544         g = []
2025-07-02 06:41:16.544         if alo < ahi:
2025-07-02 06:41:16.544             if blo < bhi:
2025-07-02 06:41:16.544                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.544             else:
2025-07-02 06:41:16.544                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.544         elif blo < bhi:
2025-07-02 06:41:16.544             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.544
2025-07-02 06:41:16.544 >       yield from g
2025-07-02 06:41:16.544
2025-07-02 06:41:16.544 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.544 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.544
2025-07-02 06:41:16.545 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.545 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.545 alo = 76, ahi = 1101
2025-07-02 06:41:16.545 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.545 blo = 76, bhi = 1101
2025-07-02 06:41:16.545
2025-07-02 06:41:16.545     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.545         r"""
2025-07-02 06:41:16.545         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.545         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.545         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.545         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.545
2025-07-02 06:41:16.545         Example:
2025-07-02 06:41:16.545
2025-07-02 06:41:16.545         >>> d = Differ()
2025-07-02 06:41:16.545         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.545         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.545         >>> print(''.join(results), end="")
2025-07-02 06:41:16.545         - abcDefghiJkl
2025-07-02 06:41:16.546         + abcdefGhijkl
2025-07-02 06:41:16.546         """
2025-07-02 06:41:16.546
2025-07-02 06:41:16.546         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.546         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.546         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.546         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.546         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.546
2025-07-02 06:41:16.546         # search for the pair that matches best without being identical
2025-07-02 06:41:16.546         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.546         # on junk -- unless we have to)
2025-07-02 06:41:16.546         for j in range(blo, bhi):
2025-07-02 06:41:16.546             bj = b[j]
2025-07-02 06:41:16.546             cruncher.set_seq2(bj)
2025-07-02 06:41:16.546             for i in range(alo, ahi):
2025-07-02 06:41:16.546                 ai = a[i]
2025-07-02 06:41:16.546                 if ai == bj:
2025-07-02 06:41:16.546                     if eqi is None:
2025-07-02 06:41:16.547                         eqi, eqj = i, j
2025-07-02 06:41:16.547                     continue
2025-07-02 06:41:16.547                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.547                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.547                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.547                 # compares by a factor of 3.
2025-07-02 06:41:16.547                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.547                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.547                 # of the computation is cached by cruncher
2025-07-02 06:41:16.547                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.547                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.547                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.547                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.547         if best_ratio < cutoff:
2025-07-02 06:41:16.547             # no non-identical "pretty close" pair
2025-07-02 06:41:16.547             if eqi is None:
2025-07-02 06:41:16.547                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.548                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.548                 return
2025-07-02 06:41:16.548             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.548             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.548         else:
2025-07-02 06:41:16.548             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.548             eqi = None
2025-07-02 06:41:16.548
2025-07-02 06:41:16.548         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.548         # identical
2025-07-02 06:41:16.548
2025-07-02 06:41:16.548         # pump out diffs from before the synch point
2025-07-02 06:41:16.548         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.548
2025-07-02 06:41:16.548         # do intraline marking on the synch pair
2025-07-02 06:41:16.548         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.548         if eqi is None:
2025-07-02 06:41:16.548             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.548             atags = btags = ""
2025-07-02 06:41:16.548             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.549             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.549                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.549                 if tag == 'replace':
2025-07-02 06:41:16.549                     atags += '^' * la
2025-07-02 06:41:16.549                     btags += '^' * lb
2025-07-02 06:41:16.549                 elif tag == 'delete':
2025-07-02 06:41:16.549                     atags += '-' * la
2025-07-02 06:41:16.549                 elif tag == 'insert':
2025-07-02 06:41:16.549                     btags += '+' * lb
2025-07-02 06:41:16.549                 elif tag == 'equal':
2025-07-02 06:41:16.549                     atags += ' ' * la
2025-07-02 06:41:16.549                     btags += ' ' * lb
2025-07-02 06:41:16.549                 else:
2025-07-02 06:41:16.549                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.549             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.549         else:
2025-07-02 06:41:16.549             # the synch pair is identical
2025-07-02 06:41:16.549             yield '  ' + aelt
2025-07-02 06:41:16.549
2025-07-02 06:41:16.549         # pump out diffs from after the synch point
2025-07-02 06:41:16.550 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.550
2025-07-02 06:41:16.550 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.550 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.550
2025-07-02 06:41:16.550 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.550 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.550 alo = 77, ahi = 1101
2025-07-02 06:41:16.550 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.550 blo = 77, bhi = 1101
2025-07-02 06:41:16.550
2025-07-02 06:41:16.550     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.550         g = []
2025-07-02 06:41:16.550         if alo < ahi:
2025-07-02 06:41:16.550             if blo < bhi:
2025-07-02 06:41:16.550                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.550             else:
2025-07-02 06:41:16.550                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.550         elif blo < bhi:
2025-07-02 06:41:16.550             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551 >       yield from g
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.551 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.551 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.551 alo = 77, ahi = 1101
2025-07-02 06:41:16.551 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.551 blo = 77, bhi = 1101
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.551         r"""
2025-07-02 06:41:16.551         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.551         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.551         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.551         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.551
2025-07-02 06:41:16.551         Example:
2025-07-02 06:41:16.552
2025-07-02 06:41:16.552         >>> d = Differ()
2025-07-02 06:41:16.552         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.552         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.552         >>> print(''.join(results), end="")
2025-07-02 06:41:16.552         - abcDefghiJkl
2025-07-02 06:41:16.552         + abcdefGhijkl
2025-07-02 06:41:16.552         """
2025-07-02 06:41:16.552
2025-07-02 06:41:16.552         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.552         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.552         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.552         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.552         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.552
2025-07-02 06:41:16.552         # search for the pair that matches best without being identical
2025-07-02 06:41:16.552         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.552         # on junk -- unless we have to)
2025-07-02 06:41:16.553         for j in range(blo, bhi):
2025-07-02 06:41:16.553             bj = b[j]
2025-07-02 06:41:16.553             cruncher.set_seq2(bj)
2025-07-02 06:41:16.553             for i in range(alo, ahi):
2025-07-02 06:41:16.553                 ai = a[i]
2025-07-02 06:41:16.553                 if ai == bj:
2025-07-02 06:41:16.553                     if eqi is None:
2025-07-02 06:41:16.553                         eqi, eqj = i, j
2025-07-02 06:41:16.553                     continue
2025-07-02 06:41:16.553                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.553                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.553                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.553                 # compares by a factor of 3.
2025-07-02 06:41:16.553                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.553                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.553                 # of the computation is cached by cruncher
2025-07-02 06:41:16.553                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.553                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.553                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.553                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.554         if best_ratio < cutoff:
2025-07-02 06:41:16.554             # no non-identical "pretty close" pair
2025-07-02 06:41:16.554             if eqi is None:
2025-07-02 06:41:16.554                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.554                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.554                 return
2025-07-02 06:41:16.554             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.554             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.554         else:
2025-07-02 06:41:16.554             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.554             eqi = None
2025-07-02 06:41:16.554
2025-07-02 06:41:16.554         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.554         # identical
2025-07-02 06:41:16.554
2025-07-02 06:41:16.554         # pump out diffs from before the synch point
2025-07-02 06:41:16.554         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.554
2025-07-02 06:41:16.554         # do intraline marking on the synch pair
2025-07-02 06:41:16.554         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.554         if eqi is None:
2025-07-02 06:41:16.555             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.555             atags = btags = ""
2025-07-02 06:41:16.555             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.555             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.555                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.555                 if tag == 'replace':
2025-07-02 06:41:16.555                     atags += '^' * la
2025-07-02 06:41:16.555                     btags += '^' * lb
2025-07-02 06:41:16.555                 elif tag == 'delete':
2025-07-02 06:41:16.555                     atags += '-' * la
2025-07-02 06:41:16.555                 elif tag == 'insert':
2025-07-02 06:41:16.555                     btags += '+' * lb
2025-07-02 06:41:16.555                 elif tag == 'equal':
2025-07-02 06:41:16.555                     atags += ' ' * la
2025-07-02 06:41:16.555                     btags += ' ' * lb
2025-07-02 06:41:16.555                 else:
2025-07-02 06:41:16.555                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.556             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.556         else:
2025-07-02 06:41:16.556             # the synch pair is identical
2025-07-02 06:41:16.556             yield '  ' + aelt
2025-07-02 06:41:16.556
2025-07-02 06:41:16.556         # pump out diffs from after the synch point
2025-07-02 06:41:16.556 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.556
2025-07-02 06:41:16.556 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.556 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.556
2025-07-02 06:41:16.556 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.556 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.556 alo = 78, ahi = 1101
2025-07-02 06:41:16.556 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.556 blo = 78, bhi = 1101
2025-07-02 06:41:16.556
2025-07-02 06:41:16.556     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.556         g = []
2025-07-02 06:41:16.556         if alo < ahi:
2025-07-02 06:41:16.557             if blo < bhi:
2025-07-02 06:41:16.557                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.557             else:
2025-07-02 06:41:16.557                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.557         elif blo < bhi:
2025-07-02 06:41:16.557             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.557
2025-07-02 06:41:16.557 >       yield from g
2025-07-02 06:41:16.557
2025-07-02 06:41:16.557 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.557 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.557
2025-07-02 06:41:16.557 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.557 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.557 alo = 78, ahi = 1101
2025-07-02 06:41:16.557 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.558 blo = 78, bhi = 1101
2025-07-02 06:41:16.558
2025-07-02 06:41:16.558     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.558         r"""
2025-07-02 06:41:16.558         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.558         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.558         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.558         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.558
2025-07-02 06:41:16.558         Example:
2025-07-02 06:41:16.558
2025-07-02 06:41:16.558         >>> d = Differ()
2025-07-02 06:41:16.558         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.558         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.558         >>> print(''.join(results), end="")
2025-07-02 06:41:16.558         - abcDefghiJkl
2025-07-02 06:41:16.558         + abcdefGhijkl
2025-07-02 06:41:16.559         """
2025-07-02 06:41:16.559
2025-07-02 06:41:16.559         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.559         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.559         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.559         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.559         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.559
2025-07-02 06:41:16.559         # search for the pair that matches best without being identical
2025-07-02 06:41:16.559         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.559         # on junk -- unless we have to)
2025-07-02 06:41:16.559         for j in range(blo, bhi):
2025-07-02 06:41:16.559             bj = b[j]
2025-07-02 06:41:16.559             cruncher.set_seq2(bj)
2025-07-02 06:41:16.559             for i in range(alo, ahi):
2025-07-02 06:41:16.559                 ai = a[i]
2025-07-02 06:41:16.559                 if ai == bj:
2025-07-02 06:41:16.559                     if eqi is None:
2025-07-02 06:41:16.559                         eqi, eqj = i, j
2025-07-02 06:41:16.559                     continue
2025-07-02 06:41:16.559                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.560                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.560                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.560                 # compares by a factor of 3.
2025-07-02 06:41:16.560                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.560                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.560                 # of the computation is cached by cruncher
2025-07-02 06:41:16.560                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.560                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.560                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.560                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.560         if best_ratio < cutoff:
2025-07-02 06:41:16.560             # no non-identical "pretty close" pair
2025-07-02 06:41:16.560             if eqi is None:
2025-07-02 06:41:16.560                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.560                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.560                 return
2025-07-02 06:41:16.560             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.560             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.560         else:
2025-07-02 06:41:16.560             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.561             eqi = None
2025-07-02 06:41:16.561
2025-07-02 06:41:16.561         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.561         # identical
2025-07-02 06:41:16.561
2025-07-02 06:41:16.561         # pump out diffs from before the synch point
2025-07-02 06:41:16.561         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.561
2025-07-02 06:41:16.561         # do intraline marking on the synch pair
2025-07-02 06:41:16.561         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.561         if eqi is None:
2025-07-02 06:41:16.561             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.561             atags = btags = ""
2025-07-02 06:41:16.561             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.561             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.561                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.561                 if tag == 'replace':
2025-07-02 06:41:16.561                     atags += '^' * la
2025-07-02 06:41:16.561                     btags += '^' * lb
2025-07-02 06:41:16.561                 elif tag == 'delete':
2025-07-02 06:41:16.562                     atags += '-' * la
2025-07-02 06:41:16.562                 elif tag == 'insert':
2025-07-02 06:41:16.562                     btags += '+' * lb
2025-07-02 06:41:16.562                 elif tag == 'equal':
2025-07-02 06:41:16.562                     atags += ' ' * la
2025-07-02 06:41:16.562                     btags += ' ' * lb
2025-07-02 06:41:16.562                 else:
2025-07-02 06:41:16.562                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.562             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.562         else:
2025-07-02 06:41:16.562             # the synch pair is identical
2025-07-02 06:41:16.562             yield '  ' + aelt
2025-07-02 06:41:16.562
2025-07-02 06:41:16.562         # pump out diffs from after the synch point
2025-07-02 06:41:16.562 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.562
2025-07-02 06:41:16.562 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.562 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.562
2025-07-02 06:41:16.562 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.562 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.563 alo = 79, ahi = 1101
2025-07-02 06:41:16.563 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.563 blo = 79, bhi = 1101
2025-07-02 06:41:16.563
2025-07-02 06:41:16.563     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.563         g = []
2025-07-02 06:41:16.563         if alo < ahi:
2025-07-02 06:41:16.563             if blo < bhi:
2025-07-02 06:41:16.563                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.563             else:
2025-07-02 06:41:16.563                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.563         elif blo < bhi:
2025-07-02 06:41:16.563             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.563
2025-07-02 06:41:16.563 >       yield from g
2025-07-02 06:41:16.563
2025-07-02 06:41:16.563 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.563 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.563
2025-07-02 06:41:16.563 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.564 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.564 alo = 79, ahi = 1101
2025-07-02 06:41:16.564 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.564 blo = 79, bhi = 1101
2025-07-02 06:41:16.564
2025-07-02 06:41:16.564     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.564         r"""
2025-07-02 06:41:16.564         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.564         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.564         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.564         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.564
2025-07-02 06:41:16.564         Example:
2025-07-02 06:41:16.564
2025-07-02 06:41:16.564         >>> d = Differ()
2025-07-02 06:41:16.564         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.564         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.565         >>> print(''.join(results), end="")
2025-07-02 06:41:16.565         - abcDefghiJkl
2025-07-02 06:41:16.565         + abcdefGhijkl
2025-07-02 06:41:16.565         """
2025-07-02 06:41:16.565
2025-07-02 06:41:16.565         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.565         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.565         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.565         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.565         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.565
2025-07-02 06:41:16.565         # search for the pair that matches best without being identical
2025-07-02 06:41:16.565         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.565         # on junk -- unless we have to)
2025-07-02 06:41:16.565         for j in range(blo, bhi):
2025-07-02 06:41:16.565             bj = b[j]
2025-07-02 06:41:16.565             cruncher.set_seq2(bj)
2025-07-02 06:41:16.565             for i in range(alo, ahi):
2025-07-02 06:41:16.566                 ai = a[i]
2025-07-02 06:41:16.566                 if ai == bj:
2025-07-02 06:41:16.566                     if eqi is None:
2025-07-02 06:41:16.566                         eqi, eqj = i, j
2025-07-02 06:41:16.566                     continue
2025-07-02 06:41:16.566                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.566                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.566                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.566                 # compares by a factor of 3.
2025-07-02 06:41:16.566                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.566                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.566                 # of the computation is cached by cruncher
2025-07-02 06:41:16.566                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.566                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.566                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.566                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.566         if best_ratio < cutoff:
2025-07-02 06:41:16.566             # no non-identical "pretty close" pair
2025-07-02 06:41:16.566             if eqi is None:
2025-07-02 06:41:16.567                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.567                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.567                 return
2025-07-02 06:41:16.567             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.567             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.567         else:
2025-07-02 06:41:16.567             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.567             eqi = None
2025-07-02 06:41:16.567
2025-07-02 06:41:16.567         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.567         # identical
2025-07-02 06:41:16.567
2025-07-02 06:41:16.567         # pump out diffs from before the synch point
2025-07-02 06:41:16.567         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.567
2025-07-02 06:41:16.567         # do intraline marking on the synch pair
2025-07-02 06:41:16.567         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.567         if eqi is None:
2025-07-02 06:41:16.567             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.567             atags = btags = ""
2025-07-02 06:41:16.567             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.568             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.568                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.568                 if tag == 'replace':
2025-07-02 06:41:16.568                     atags += '^' * la
2025-07-02 06:41:16.568                     btags += '^' * lb
2025-07-02 06:41:16.568                 elif tag == 'delete':
2025-07-02 06:41:16.568                     atags += '-' * la
2025-07-02 06:41:16.568                 elif tag == 'insert':
2025-07-02 06:41:16.568                     btags += '+' * lb
2025-07-02 06:41:16.568                 elif tag == 'equal':
2025-07-02 06:41:16.568                     atags += ' ' * la
2025-07-02 06:41:16.568                     btags += ' ' * lb
2025-07-02 06:41:16.568                 else:
2025-07-02 06:41:16.568                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.568             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.568         else:
2025-07-02 06:41:16.568             # the synch pair is identical
2025-07-02 06:41:16.568             yield '  ' + aelt
2025-07-02 06:41:16.568
2025-07-02 06:41:16.568         # pump out diffs from after the synch point
2025-07-02 06:41:16.569 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.569
2025-07-02 06:41:16.569 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.569 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.569
2025-07-02 06:41:16.569 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.569 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.569 alo = 80, ahi = 1101
2025-07-02 06:41:16.569 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.569 blo = 80, bhi = 1101
2025-07-02 06:41:16.569
2025-07-02 06:41:16.569     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.569         g = []
2025-07-02 06:41:16.569         if alo < ahi:
2025-07-02 06:41:16.569             if blo < bhi:
2025-07-02 06:41:16.569                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.569             else:
2025-07-02 06:41:16.569                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.569         elif blo < bhi:
2025-07-02 06:41:16.569             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.570
2025-07-02 06:41:16.570 >       yield from g
2025-07-02 06:41:16.570
2025-07-02 06:41:16.570 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.570 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.570
2025-07-02 06:41:16.570 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.570 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.570 alo = 80, ahi = 1101
2025-07-02 06:41:16.570 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.570 blo = 80, bhi = 1101
2025-07-02 06:41:16.570
2025-07-02 06:41:16.570     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.570         r"""
2025-07-02 06:41:16.570         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.570         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.570         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.570         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.571
2025-07-02 06:41:16.571         Example:
2025-07-02 06:41:16.571
2025-07-02 06:41:16.571         >>> d = Differ()
2025-07-02 06:41:16.571         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.571         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.571         >>> print(''.join(results), end="")
2025-07-02 06:41:16.571         - abcDefghiJkl
2025-07-02 06:41:16.571         + abcdefGhijkl
2025-07-02 06:41:16.571         """
2025-07-02 06:41:16.571
2025-07-02 06:41:16.571         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.571         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.571         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.571         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.571         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.571
2025-07-02 06:41:16.572         # search for the pair that matches best without being identical
2025-07-02 06:41:16.572         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.572         # on junk -- unless we have to)
2025-07-02 06:41:16.572         for j in range(blo, bhi):
2025-07-02 06:41:16.572             bj = b[j]
2025-07-02 06:41:16.572             cruncher.set_seq2(bj)
2025-07-02 06:41:16.572             for i in range(alo, ahi):
2025-07-02 06:41:16.572                 ai = a[i]
2025-07-02 06:41:16.572                 if ai == bj:
2025-07-02 06:41:16.572                     if eqi is None:
2025-07-02 06:41:16.572                         eqi, eqj = i, j
2025-07-02 06:41:16.572                     continue
2025-07-02 06:41:16.572                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.572                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.572                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.572                 # compares by a factor of 3.
2025-07-02 06:41:16.572                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.572                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.572                 # of the computation is cached by cruncher
2025-07-02 06:41:16.572                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.573                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.573                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.573                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.573         if best_ratio < cutoff:
2025-07-02 06:41:16.573             # no non-identical "pretty close" pair
2025-07-02 06:41:16.573             if eqi is None:
2025-07-02 06:41:16.573                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.573                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.573                 return
2025-07-02 06:41:16.573             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.573             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.573         else:
2025-07-02 06:41:16.573             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.573             eqi = None
2025-07-02 06:41:16.573
2025-07-02 06:41:16.573         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.573         # identical
2025-07-02 06:41:16.573
2025-07-02 06:41:16.574         # pump out diffs from before the synch point
2025-07-02 06:41:16.574         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.574
2025-07-02 06:41:16.574         # do intraline marking on the synch pair
2025-07-02 06:41:16.574         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.574         if eqi is None:
2025-07-02 06:41:16.574             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.574             atags = btags = ""
2025-07-02 06:41:16.574             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.574             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.574                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.574                 if tag == 'replace':
2025-07-02 06:41:16.574                     atags += '^' * la
2025-07-02 06:41:16.574                     btags += '^' * lb
2025-07-02 06:41:16.574                 elif tag == 'delete':
2025-07-02 06:41:16.574                     atags += '-' * la
2025-07-02 06:41:16.574                 elif tag == 'insert':
2025-07-02 06:41:16.574                     btags += '+' * lb
2025-07-02 06:41:16.574                 elif tag == 'equal':
2025-07-02 06:41:16.574                     atags += ' ' * la
2025-07-02 06:41:16.575                     btags += ' ' * lb
2025-07-02 06:41:16.575                 else:
2025-07-02 06:41:16.575                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.575             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.575         else:
2025-07-02 06:41:16.575             # the synch pair is identical
2025-07-02 06:41:16.575             yield '  ' + aelt
2025-07-02 06:41:16.575
2025-07-02 06:41:16.575         # pump out diffs from after the synch point
2025-07-02 06:41:16.575 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.575
2025-07-02 06:41:16.575 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.575 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.575
2025-07-02 06:41:16.575 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.575 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.575 alo = 81, ahi = 1101
2025-07-02 06:41:16.575 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.575 blo = 81, bhi = 1101
2025-07-02 06:41:16.576
2025-07-02 06:41:16.576     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.576         g = []
2025-07-02 06:41:16.576         if alo < ahi:
2025-07-02 06:41:16.576             if blo < bhi:
2025-07-02 06:41:16.576                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.576             else:
2025-07-02 06:41:16.576                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.576         elif blo < bhi:
2025-07-02 06:41:16.576             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.576
2025-07-02 06:41:16.576 >       yield from g
2025-07-02 06:41:16.576
2025-07-02 06:41:16.576 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.576 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.576
2025-07-02 06:41:16.576 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.576 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.576 alo = 81, ahi = 1101
2025-07-02 06:41:16.576 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.577 blo = 81, bhi = 1101
2025-07-02 06:41:16.577
2025-07-02 06:41:16.577     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.577         r"""
2025-07-02 06:41:16.577         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.577         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.577         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.577         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.577
2025-07-02 06:41:16.577         Example:
2025-07-02 06:41:16.577
2025-07-02 06:41:16.577         >>> d = Differ()
2025-07-02 06:41:16.577         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.577         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.577         >>> print(''.join(results), end="")
2025-07-02 06:41:16.577         - abcDefghiJkl
2025-07-02 06:41:16.577         + abcdefGhijkl
2025-07-02 06:41:16.577         """
2025-07-02 06:41:16.577
2025-07-02 06:41:16.578         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.578         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.578         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.578         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.578         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.578
2025-07-02 06:41:16.578         # search for the pair that matches best without being identical
2025-07-02 06:41:16.578         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.578         # on junk -- unless we have to)
2025-07-02 06:41:16.578         for j in range(blo, bhi):
2025-07-02 06:41:16.578             bj = b[j]
2025-07-02 06:41:16.578             cruncher.set_seq2(bj)
2025-07-02 06:41:16.578             for i in range(alo, ahi):
2025-07-02 06:41:16.578                 ai = a[i]
2025-07-02 06:41:16.578                 if ai == bj:
2025-07-02 06:41:16.578                     if eqi is None:
2025-07-02 06:41:16.578                         eqi, eqj = i, j
2025-07-02 06:41:16.578                     continue
2025-07-02 06:41:16.578                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.578                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.579                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.579                 # compares by a factor of 3.
2025-07-02 06:41:16.579                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.579                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.579                 # of the computation is cached by cruncher
2025-07-02 06:41:16.579                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.579                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.579                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.579                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.579         if best_ratio < cutoff:
2025-07-02 06:41:16.579             # no non-identical "pretty close" pair
2025-07-02 06:41:16.579             if eqi is None:
2025-07-02 06:41:16.579                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.579                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.579                 return
2025-07-02 06:41:16.579             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.579             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.579         else:
2025-07-02 06:41:16.579             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.579             eqi = None
2025-07-02 06:41:16.580
2025-07-02 06:41:16.580         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.580         # identical
2025-07-02 06:41:16.580
2025-07-02 06:41:16.580         # pump out diffs from before the synch point
2025-07-02 06:41:16.580         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.580
2025-07-02 06:41:16.580         # do intraline marking on the synch pair
2025-07-02 06:41:16.580         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.580         if eqi is None:
2025-07-02 06:41:16.580             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.580             atags = btags = ""
2025-07-02 06:41:16.580             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.580             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.580                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.580                 if tag == 'replace':
2025-07-02 06:41:16.580                     atags += '^' * la
2025-07-02 06:41:16.580                     btags += '^' * lb
2025-07-02 06:41:16.580                 elif tag == 'delete':
2025-07-02 06:41:16.580                     atags += '-' * la
2025-07-02 06:41:16.580                 elif tag == 'insert':
2025-07-02 06:41:16.581                     btags += '+' * lb
2025-07-02 06:41:16.581                 elif tag == 'equal':
2025-07-02 06:41:16.581                     atags += ' ' * la
2025-07-02 06:41:16.581                     btags += ' ' * lb
2025-07-02 06:41:16.581                 else:
2025-07-02 06:41:16.581                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.581             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.581         else:
2025-07-02 06:41:16.581             # the synch pair is identical
2025-07-02 06:41:16.581             yield '  ' + aelt
2025-07-02 06:41:16.581
2025-07-02 06:41:16.581         # pump out diffs from after the synch point
2025-07-02 06:41:16.581 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.581
2025-07-02 06:41:16.581 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.581 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.581
2025-07-02 06:41:16.581 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.581 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.581 alo = 82, ahi = 1101
2025-07-02 06:41:16.582 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.582 blo = 82, bhi = 1101
2025-07-02 06:41:16.582
2025-07-02 06:41:16.582     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.582         g = []
2025-07-02 06:41:16.582         if alo < ahi:
2025-07-02 06:41:16.582             if blo < bhi:
2025-07-02 06:41:16.582                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.582             else:
2025-07-02 06:41:16.582                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.582         elif blo < bhi:
2025-07-02 06:41:16.582             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.582
2025-07-02 06:41:16.582 >       yield from g
2025-07-02 06:41:16.582
2025-07-02 06:41:16.582 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.582 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.582
2025-07-02 06:41:16.582 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.583 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.583 alo = 82, ahi = 1101
2025-07-02 06:41:16.583 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.583 blo = 82, bhi = 1101
2025-07-02 06:41:16.583
2025-07-02 06:41:16.583     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.583         r"""
2025-07-02 06:41:16.583         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.583         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.583         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.583         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.583
2025-07-02 06:41:16.583         Example:
2025-07-02 06:41:16.583
2025-07-02 06:41:16.583         >>> d = Differ()
2025-07-02 06:41:16.583         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.583         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.583         >>> print(''.join(results), end="")
2025-07-02 06:41:16.583         - abcDefghiJkl
2025-07-02 06:41:16.584         + abcdefGhijkl
2025-07-02 06:41:16.584         """
2025-07-02 06:41:16.584
2025-07-02 06:41:16.584         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.584         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.584         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.584         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.584         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.584
2025-07-02 06:41:16.584         # search for the pair that matches best without being identical
2025-07-02 06:41:16.584         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.584         # on junk -- unless we have to)
2025-07-02 06:41:16.584         for j in range(blo, bhi):
2025-07-02 06:41:16.584             bj = b[j]
2025-07-02 06:41:16.584             cruncher.set_seq2(bj)
2025-07-02 06:41:16.584             for i in range(alo, ahi):
2025-07-02 06:41:16.584                 ai = a[i]
2025-07-02 06:41:16.584                 if ai == bj:
2025-07-02 06:41:16.585                     if eqi is None:
2025-07-02 06:41:16.585                         eqi, eqj = i, j
2025-07-02 06:41:16.585                     continue
2025-07-02 06:41:16.585                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.585                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.585                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.585                 # compares by a factor of 3.
2025-07-02 06:41:16.585                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.585                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.585                 # of the computation is cached by cruncher
2025-07-02 06:41:16.585                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.585                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.585                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.585                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.585         if best_ratio < cutoff:
2025-07-02 06:41:16.585             # no non-identical "pretty close" pair
2025-07-02 06:41:16.585             if eqi is None:
2025-07-02 06:41:16.585                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.586                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.586                 return
2025-07-02 06:41:16.586             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.586             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.586         else:
2025-07-02 06:41:16.586             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.586             eqi = None
2025-07-02 06:41:16.586
2025-07-02 06:41:16.586         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.586         # identical
2025-07-02 06:41:16.586
2025-07-02 06:41:16.586         # pump out diffs from before the synch point
2025-07-02 06:41:16.586         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.586
2025-07-02 06:41:16.586         # do intraline marking on the synch pair
2025-07-02 06:41:16.586         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.586         if eqi is None:
2025-07-02 06:41:16.586             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.586             atags = btags = ""
2025-07-02 06:41:16.586             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.587             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.587                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.587                 if tag == 'replace':
2025-07-02 06:41:16.587                     atags += '^' * la
2025-07-02 06:41:16.587                     btags += '^' * lb
2025-07-02 06:41:16.587                 elif tag == 'delete':
2025-07-02 06:41:16.587                     atags += '-' * la
2025-07-02 06:41:16.587                 elif tag == 'insert':
2025-07-02 06:41:16.587                     btags += '+' * lb
2025-07-02 06:41:16.587                 elif tag == 'equal':
2025-07-02 06:41:16.587                     atags += ' ' * la
2025-07-02 06:41:16.587                     btags += ' ' * lb
2025-07-02 06:41:16.587                 else:
2025-07-02 06:41:16.587                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.587             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.587         else:
2025-07-02 06:41:16.587             # the synch pair is identical
2025-07-02 06:41:16.587             yield '  ' + aelt
2025-07-02 06:41:16.587
2025-07-02 06:41:16.587         # pump out diffs from after the synch point
2025-07-02 06:41:16.588 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.588
2025-07-02 06:41:16.588 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.588 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.588
2025-07-02 06:41:16.588 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.588 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.588 alo = 83, ahi = 1101
2025-07-02 06:41:16.588 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.588 blo = 83, bhi = 1101
2025-07-02 06:41:16.588
2025-07-02 06:41:16.588     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.588         g = []
2025-07-02 06:41:16.588         if alo < ahi:
2025-07-02 06:41:16.588             if blo < bhi:
2025-07-02 06:41:16.588                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.588             else:
2025-07-02 06:41:16.588                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.588         elif blo < bhi:
2025-07-02 06:41:16.588             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589 >       yield from g
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.589 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.589 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.589 alo = 83, ahi = 1101
2025-07-02 06:41:16.589 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.589 blo = 83, bhi = 1101
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.589         r"""
2025-07-02 06:41:16.589         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.589         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.589         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.589         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.589
2025-07-02 06:41:16.589         Example:
2025-07-02 06:41:16.590
2025-07-02 06:41:16.590         >>> d = Differ()
2025-07-02 06:41:16.590         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.590         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.590         >>> print(''.join(results), end="")
2025-07-02 06:41:16.590         - abcDefghiJkl
2025-07-02 06:41:16.590         + abcdefGhijkl
2025-07-02 06:41:16.590         """
2025-07-02 06:41:16.590
2025-07-02 06:41:16.590         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.590         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.590         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.590         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.590         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.590
2025-07-02 06:41:16.590         # search for the pair that matches best without being identical
2025-07-02 06:41:16.591         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.591         # on junk -- unless we have to)
2025-07-02 06:41:16.591         for j in range(blo, bhi):
2025-07-02 06:41:16.591             bj = b[j]
2025-07-02 06:41:16.591             cruncher.set_seq2(bj)
2025-07-02 06:41:16.591             for i in range(alo, ahi):
2025-07-02 06:41:16.591                 ai = a[i]
2025-07-02 06:41:16.591                 if ai == bj:
2025-07-02 06:41:16.591                     if eqi is None:
2025-07-02 06:41:16.591                         eqi, eqj = i, j
2025-07-02 06:41:16.591                     continue
2025-07-02 06:41:16.591                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.591                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.591                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.591                 # compares by a factor of 3.
2025-07-02 06:41:16.591                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.591                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.591                 # of the computation is cached by cruncher
2025-07-02 06:41:16.591                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.592                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.592                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.592                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.592         if best_ratio < cutoff:
2025-07-02 06:41:16.592             # no non-identical "pretty close" pair
2025-07-02 06:41:16.592             if eqi is None:
2025-07-02 06:41:16.592                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.592                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.592                 return
2025-07-02 06:41:16.592             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.592             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.592         else:
2025-07-02 06:41:16.592             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.592             eqi = None
2025-07-02 06:41:16.592
2025-07-02 06:41:16.592         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.592         # identical
2025-07-02 06:41:16.592
2025-07-02 06:41:16.592         # pump out diffs from before the synch point
2025-07-02 06:41:16.592         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.593
2025-07-02 06:41:16.593         # do intraline marking on the synch pair
2025-07-02 06:41:16.593         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.593         if eqi is None:
2025-07-02 06:41:16.593             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.593             atags = btags = ""
2025-07-02 06:41:16.593             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.593             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.593                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.593                 if tag == 'replace':
2025-07-02 06:41:16.593                     atags += '^' * la
2025-07-02 06:41:16.593                     btags += '^' * lb
2025-07-02 06:41:16.593                 elif tag == 'delete':
2025-07-02 06:41:16.593                     atags += '-' * la
2025-07-02 06:41:16.593                 elif tag == 'insert':
2025-07-02 06:41:16.593                     btags += '+' * lb
2025-07-02 06:41:16.593                 elif tag == 'equal':
2025-07-02 06:41:16.593                     atags += ' ' * la
2025-07-02 06:41:16.593                     btags += ' ' * lb
2025-07-02 06:41:16.593                 else:
2025-07-02 06:41:16.594                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.594             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.594         else:
2025-07-02 06:41:16.594             # the synch pair is identical
2025-07-02 06:41:16.594             yield '  ' + aelt
2025-07-02 06:41:16.594
2025-07-02 06:41:16.594         # pump out diffs from after the synch point
2025-07-02 06:41:16.594 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.594
2025-07-02 06:41:16.594 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.594 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.594
2025-07-02 06:41:16.594 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.594 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.594 alo = 84, ahi = 1101
2025-07-02 06:41:16.594 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.594 blo = 84, bhi = 1101
2025-07-02 06:41:16.594
2025-07-02 06:41:16.594     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.594         g = []
2025-07-02 06:41:16.594         if alo < ahi:
2025-07-02 06:41:16.595             if blo < bhi:
2025-07-02 06:41:16.595                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.595             else:
2025-07-02 06:41:16.595                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.595         elif blo < bhi:
2025-07-02 06:41:16.595             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.595
2025-07-02 06:41:16.595 >       yield from g
2025-07-02 06:41:16.595
2025-07-02 06:41:16.595 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.595 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.595
2025-07-02 06:41:16.595 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.595 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.595 alo = 84, ahi = 1101
2025-07-02 06:41:16.595 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.595 blo = 84, bhi = 1101
2025-07-02 06:41:16.595
2025-07-02 06:41:16.595     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.595         r"""
2025-07-02 06:41:16.596         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.596         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.596         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.596         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.596
2025-07-02 06:41:16.596         Example:
2025-07-02 06:41:16.596
2025-07-02 06:41:16.596         >>> d = Differ()
2025-07-02 06:41:16.596         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.596         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.596         >>> print(''.join(results), end="")
2025-07-02 06:41:16.596         - abcDefghiJkl
2025-07-02 06:41:16.596         + abcdefGhijkl
2025-07-02 06:41:16.596         """
2025-07-02 06:41:16.596
2025-07-02 06:41:16.596         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.596         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.596         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.597         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.597         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.597
2025-07-02 06:41:16.597         # search for the pair that matches best without being identical
2025-07-02 06:41:16.597         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.597         # on junk -- unless we have to)
2025-07-02 06:41:16.597         for j in range(blo, bhi):
2025-07-02 06:41:16.597             bj = b[j]
2025-07-02 06:41:16.597             cruncher.set_seq2(bj)
2025-07-02 06:41:16.597             for i in range(alo, ahi):
2025-07-02 06:41:16.597                 ai = a[i]
2025-07-02 06:41:16.597                 if ai == bj:
2025-07-02 06:41:16.597                     if eqi is None:
2025-07-02 06:41:16.597                         eqi, eqj = i, j
2025-07-02 06:41:16.597                     continue
2025-07-02 06:41:16.597                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.597                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.597                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.597                 # compares by a factor of 3.
2025-07-02 06:41:16.597                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.597                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.598                 # of the computation is cached by cruncher
2025-07-02 06:41:16.598                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.598                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.598                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.598                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.598         if best_ratio < cutoff:
2025-07-02 06:41:16.598             # no non-identical "pretty close" pair
2025-07-02 06:41:16.598             if eqi is None:
2025-07-02 06:41:16.598                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.598                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.598                 return
2025-07-02 06:41:16.598             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.598             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.598         else:
2025-07-02 06:41:16.598             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.598             eqi = None
2025-07-02 06:41:16.598
2025-07-02 06:41:16.598         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.598         # identical
2025-07-02 06:41:16.598
2025-07-02 06:41:16.599         # pump out diffs from before the synch point
2025-07-02 06:41:16.599         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.599
2025-07-02 06:41:16.599         # do intraline marking on the synch pair
2025-07-02 06:41:16.599         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.599         if eqi is None:
2025-07-02 06:41:16.599             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.599             atags = btags = ""
2025-07-02 06:41:16.599             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.599             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.599                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.599                 if tag == 'replace':
2025-07-02 06:41:16.599                     atags += '^' * la
2025-07-02 06:41:16.599                     btags += '^' * lb
2025-07-02 06:41:16.599                 elif tag == 'delete':
2025-07-02 06:41:16.599                     atags += '-' * la
2025-07-02 06:41:16.599                 elif tag == 'insert':
2025-07-02 06:41:16.599                     btags += '+' * lb
2025-07-02 06:41:16.600                 elif tag == 'equal':
2025-07-02 06:41:16.600                     atags += ' ' * la
2025-07-02 06:41:16.600                     btags += ' ' * lb
2025-07-02 06:41:16.600                 else:
2025-07-02 06:41:16.600                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.600             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.600         else:
2025-07-02 06:41:16.600             # the synch pair is identical
2025-07-02 06:41:16.600             yield '  ' + aelt
2025-07-02 06:41:16.600
2025-07-02 06:41:16.600         # pump out diffs from after the synch point
2025-07-02 06:41:16.600 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.600
2025-07-02 06:41:16.600 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.600 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.600
2025-07-02 06:41:16.600 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.600 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.600 alo = 85, ahi = 1101
2025-07-02 06:41:16.600 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.601 blo = 85, bhi = 1101
2025-07-02 06:41:16.601
2025-07-02 06:41:16.601     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.601         g = []
2025-07-02 06:41:16.601         if alo < ahi:
2025-07-02 06:41:16.601             if blo < bhi:
2025-07-02 06:41:16.601                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.601             else:
2025-07-02 06:41:16.601                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.601         elif blo < bhi:
2025-07-02 06:41:16.601             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.601
2025-07-02 06:41:16.601 >       yield from g
2025-07-02 06:41:16.601
2025-07-02 06:41:16.601 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.601 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.601
2025-07-02 06:41:16.601 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.602 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.602 alo = 85, ahi = 1101
2025-07-02 06:41:16.602 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.602 blo = 85, bhi = 1101
2025-07-02 06:41:16.602
2025-07-02 06:41:16.602     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.602         r"""
2025-07-02 06:41:16.602         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.602         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.602         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.602         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.602
2025-07-02 06:41:16.602         Example:
2025-07-02 06:41:16.602
2025-07-02 06:41:16.602         >>> d = Differ()
2025-07-02 06:41:16.602         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.602         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.602         >>> print(''.join(results), end="")
2025-07-02 06:41:16.602         - abcDefghiJkl
2025-07-02 06:41:16.603         + abcdefGhijkl
2025-07-02 06:41:16.603         """
2025-07-02 06:41:16.603
2025-07-02 06:41:16.603         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.603         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.603         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.603         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.603         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.603
2025-07-02 06:41:16.603         # search for the pair that matches best without being identical
2025-07-02 06:41:16.603         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.603         # on junk -- unless we have to)
2025-07-02 06:41:16.603         for j in range(blo, bhi):
2025-07-02 06:41:16.603             bj = b[j]
2025-07-02 06:41:16.603             cruncher.set_seq2(bj)
2025-07-02 06:41:16.603             for i in range(alo, ahi):
2025-07-02 06:41:16.603                 ai = a[i]
2025-07-02 06:41:16.603                 if ai == bj:
2025-07-02 06:41:16.603                     if eqi is None:
2025-07-02 06:41:16.604                         eqi, eqj = i, j
2025-07-02 06:41:16.604                     continue
2025-07-02 06:41:16.604                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.604                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.604                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.604                 # compares by a factor of 3.
2025-07-02 06:41:16.604                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.604                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.604                 # of the computation is cached by cruncher
2025-07-02 06:41:16.604                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.604                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.604                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.604                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.604         if best_ratio < cutoff:
2025-07-02 06:41:16.604             # no non-identical "pretty close" pair
2025-07-02 06:41:16.604             if eqi is None:
2025-07-02 06:41:16.604                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.604                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.604                 return
2025-07-02 06:41:16.604             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.604             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.605         else:
2025-07-02 06:41:16.605             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.605             eqi = None
2025-07-02 06:41:16.605
2025-07-02 06:41:16.605         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.605         # identical
2025-07-02 06:41:16.605
2025-07-02 06:41:16.605         # pump out diffs from before the synch point
2025-07-02 06:41:16.605         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.605
2025-07-02 06:41:16.605         # do intraline marking on the synch pair
2025-07-02 06:41:16.605         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.605         if eqi is None:
2025-07-02 06:41:16.605             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.605             atags = btags = ""
2025-07-02 06:41:16.605             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.605             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.605                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.605                 if tag == 'replace':
2025-07-02 06:41:16.605                     atags += '^' * la
2025-07-02 06:41:16.606                     btags += '^' * lb
2025-07-02 06:41:16.606                 elif tag == 'delete':
2025-07-02 06:41:16.606                     atags += '-' * la
2025-07-02 06:41:16.606                 elif tag == 'insert':
2025-07-02 06:41:16.606                     btags += '+' * lb
2025-07-02 06:41:16.606                 elif tag == 'equal':
2025-07-02 06:41:16.606                     atags += ' ' * la
2025-07-02 06:41:16.606                     btags += ' ' * lb
2025-07-02 06:41:16.606                 else:
2025-07-02 06:41:16.606                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.606             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.606         else:
2025-07-02 06:41:16.606             # the synch pair is identical
2025-07-02 06:41:16.606             yield '  ' + aelt
2025-07-02 06:41:16.606
2025-07-02 06:41:16.606         # pump out diffs from after the synch point
2025-07-02 06:41:16.606 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.606
2025-07-02 06:41:16.606 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.606 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.607
2025-07-02 06:41:16.607 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.607 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.607 alo = 86, ahi = 1101
2025-07-02 06:41:16.607 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.607 blo = 86, bhi = 1101
2025-07-02 06:41:16.607
2025-07-02 06:41:16.607     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.607         g = []
2025-07-02 06:41:16.607         if alo < ahi:
2025-07-02 06:41:16.607             if blo < bhi:
2025-07-02 06:41:16.607                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.607             else:
2025-07-02 06:41:16.607                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.607         elif blo < bhi:
2025-07-02 06:41:16.607             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.607
2025-07-02 06:41:16.607 >       yield from g
2025-07-02 06:41:16.607
2025-07-02 06:41:16.607 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.607 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.608
2025-07-02 06:41:16.608 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.608 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.608 alo = 86, ahi = 1101
2025-07-02 06:41:16.608 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.608 blo = 86, bhi = 1101
2025-07-02 06:41:16.608
2025-07-02 06:41:16.608     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.608         r"""
2025-07-02 06:41:16.608         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.608         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.608         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.608         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.608
2025-07-02 06:41:16.608         Example:
2025-07-02 06:41:16.608
2025-07-02 06:41:16.608         >>> d = Differ()
2025-07-02 06:41:16.608         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.609         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.609         >>> print(''.join(results), end="")
2025-07-02 06:41:16.609         - abcDefghiJkl
2025-07-02 06:41:16.609         + abcdefGhijkl
2025-07-02 06:41:16.609         """
2025-07-02 06:41:16.609
2025-07-02 06:41:16.609         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.609         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.609         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.609         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.609         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.609
2025-07-02 06:41:16.609         # search for the pair that matches best without being identical
2025-07-02 06:41:16.609         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.609         # on junk -- unless we have to)
2025-07-02 06:41:16.609         for j in range(blo, bhi):
2025-07-02 06:41:16.609             bj = b[j]
2025-07-02 06:41:16.609             cruncher.set_seq2(bj)
2025-07-02 06:41:16.610             for i in range(alo, ahi):
2025-07-02 06:41:16.610                 ai = a[i]
2025-07-02 06:41:16.610                 if ai == bj:
2025-07-02 06:41:16.610                     if eqi is None:
2025-07-02 06:41:16.610                         eqi, eqj = i, j
2025-07-02 06:41:16.610                     continue
2025-07-02 06:41:16.610                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.610                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.610                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.610                 # compares by a factor of 3.
2025-07-02 06:41:16.610                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.610                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.610                 # of the computation is cached by cruncher
2025-07-02 06:41:16.610                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.610                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.610                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.610                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.610         if best_ratio < cutoff:
2025-07-02 06:41:16.610             # no non-identical "pretty close" pair
2025-07-02 06:41:16.610             if eqi is None:
2025-07-02 06:41:16.611                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.611                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.611                 return
2025-07-02 06:41:16.611             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.611             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.611         else:
2025-07-02 06:41:16.611             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.611             eqi = None
2025-07-02 06:41:16.611
2025-07-02 06:41:16.611         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.611         # identical
2025-07-02 06:41:16.611
2025-07-02 06:41:16.611         # pump out diffs from before the synch point
2025-07-02 06:41:16.611         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.611
2025-07-02 06:41:16.611         # do intraline marking on the synch pair
2025-07-02 06:41:16.611         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.611         if eqi is None:
2025-07-02 06:41:16.611             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.611             atags = btags = ""
2025-07-02 06:41:16.612             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.612             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.612                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.612                 if tag == 'replace':
2025-07-02 06:41:16.612                     atags += '^' * la
2025-07-02 06:41:16.612                     btags += '^' * lb
2025-07-02 06:41:16.612                 elif tag == 'delete':
2025-07-02 06:41:16.612                     atags += '-' * la
2025-07-02 06:41:16.612                 elif tag == 'insert':
2025-07-02 06:41:16.612                     btags += '+' * lb
2025-07-02 06:41:16.612                 elif tag == 'equal':
2025-07-02 06:41:16.612                     atags += ' ' * la
2025-07-02 06:41:16.612                     btags += ' ' * lb
2025-07-02 06:41:16.612                 else:
2025-07-02 06:41:16.612                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.612             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.612         else:
2025-07-02 06:41:16.612             # the synch pair is identical
2025-07-02 06:41:16.612             yield '  ' + aelt
2025-07-02 06:41:16.612
2025-07-02 06:41:16.613         # pump out diffs from after the synch point
2025-07-02 06:41:16.613 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.613
2025-07-02 06:41:16.613 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.613 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.613
2025-07-02 06:41:16.613 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.613 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.613 alo = 87, ahi = 1101
2025-07-02 06:41:16.613 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.613 blo = 87, bhi = 1101
2025-07-02 06:41:16.613
2025-07-02 06:41:16.613     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.613         g = []
2025-07-02 06:41:16.613         if alo < ahi:
2025-07-02 06:41:16.613             if blo < bhi:
2025-07-02 06:41:16.613                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.613             else:
2025-07-02 06:41:16.613                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.613         elif blo < bhi:
2025-07-02 06:41:16.614             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614 >       yield from g
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.614 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.614 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.614 alo = 87, ahi = 1101
2025-07-02 06:41:16.614 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.614 blo = 87, bhi = 1101
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.614         r"""
2025-07-02 06:41:16.614         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.614         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.614         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.614         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.614
2025-07-02 06:41:16.614         Example:
2025-07-02 06:41:16.615
2025-07-02 06:41:16.615         >>> d = Differ()
2025-07-02 06:41:16.615         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.615         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.615         >>> print(''.join(results), end="")
2025-07-02 06:41:16.615         - abcDefghiJkl
2025-07-02 06:41:16.615         + abcdefGhijkl
2025-07-02 06:41:16.615         """
2025-07-02 06:41:16.615
2025-07-02 06:41:16.615         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.615         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.615         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.615         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.615         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.615
2025-07-02 06:41:16.615         # search for the pair that matches best without being identical
2025-07-02 06:41:16.615         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.615         # on junk -- unless we have to)
2025-07-02 06:41:16.616         for j in range(blo, bhi):
2025-07-02 06:41:16.616             bj = b[j]
2025-07-02 06:41:16.616             cruncher.set_seq2(bj)
2025-07-02 06:41:16.616             for i in range(alo, ahi):
2025-07-02 06:41:16.616                 ai = a[i]
2025-07-02 06:41:16.616                 if ai == bj:
2025-07-02 06:41:16.616                     if eqi is None:
2025-07-02 06:41:16.616                         eqi, eqj = i, j
2025-07-02 06:41:16.616                     continue
2025-07-02 06:41:16.616                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.616                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.616                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.616                 # compares by a factor of 3.
2025-07-02 06:41:16.616                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.616                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.616                 # of the computation is cached by cruncher
2025-07-02 06:41:16.616                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.616                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.616                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.617                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.617         if best_ratio < cutoff:
2025-07-02 06:41:16.617             # no non-identical "pretty close" pair
2025-07-02 06:41:16.617             if eqi is None:
2025-07-02 06:41:16.617                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.617                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.617                 return
2025-07-02 06:41:16.617             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.617             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.617         else:
2025-07-02 06:41:16.617             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.617             eqi = None
2025-07-02 06:41:16.617
2025-07-02 06:41:16.617         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.617         # identical
2025-07-02 06:41:16.617
2025-07-02 06:41:16.617         # pump out diffs from before the synch point
2025-07-02 06:41:16.617         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.617
2025-07-02 06:41:16.618         # do intraline marking on the synch pair
2025-07-02 06:41:16.618         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.618         if eqi is None:
2025-07-02 06:41:16.618             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.618             atags = btags = ""
2025-07-02 06:41:16.618             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.618             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.618                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.618                 if tag == 'replace':
2025-07-02 06:41:16.618                     atags += '^' * la
2025-07-02 06:41:16.618                     btags += '^' * lb
2025-07-02 06:41:16.618                 elif tag == 'delete':
2025-07-02 06:41:16.618                     atags += '-' * la
2025-07-02 06:41:16.618                 elif tag == 'insert':
2025-07-02 06:41:16.618                     btags += '+' * lb
2025-07-02 06:41:16.618                 elif tag == 'equal':
2025-07-02 06:41:16.618                     atags += ' ' * la
2025-07-02 06:41:16.618                     btags += ' ' * lb
2025-07-02 06:41:16.618                 else:
2025-07-02 06:41:16.619                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.619             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.619         else:
2025-07-02 06:41:16.619             # the synch pair is identical
2025-07-02 06:41:16.619             yield '  ' + aelt
2025-07-02 06:41:16.619
2025-07-02 06:41:16.619         # pump out diffs from after the synch point
2025-07-02 06:41:16.619 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.619
2025-07-02 06:41:16.619 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.619 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.619
2025-07-02 06:41:16.619 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.619 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.619 alo = 88, ahi = 1101
2025-07-02 06:41:16.619 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.619 blo = 88, bhi = 1101
2025-07-02 06:41:16.619
2025-07-02 06:41:16.619     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.619         g = []
2025-07-02 06:41:16.620         if alo < ahi:
2025-07-02 06:41:16.620             if blo < bhi:
2025-07-02 06:41:16.620                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.620             else:
2025-07-02 06:41:16.620                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.620         elif blo < bhi:
2025-07-02 06:41:16.620             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.620
2025-07-02 06:41:16.620 >       yield from g
2025-07-02 06:41:16.620
2025-07-02 06:41:16.620 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.620 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.620
2025-07-02 06:41:16.620 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.620 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.620 alo = 88, ahi = 1101
2025-07-02 06:41:16.620 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.620 blo = 88, bhi = 1101
2025-07-02 06:41:16.620
2025-07-02 06:41:16.621     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.621         r"""
2025-07-02 06:41:16.621         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.621         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.621         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.621         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.621
2025-07-02 06:41:16.621         Example:
2025-07-02 06:41:16.621
2025-07-02 06:41:16.621         >>> d = Differ()
2025-07-02 06:41:16.621         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.621         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.621         >>> print(''.join(results), end="")
2025-07-02 06:41:16.621         - abcDefghiJkl
2025-07-02 06:41:16.621         + abcdefGhijkl
2025-07-02 06:41:16.621         """
2025-07-02 06:41:16.621
2025-07-02 06:41:16.621         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.622         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.622         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.622         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.622         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.622
2025-07-02 06:41:16.622         # search for the pair that matches best without being identical
2025-07-02 06:41:16.622         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.622         # on junk -- unless we have to)
2025-07-02 06:41:16.622         for j in range(blo, bhi):
2025-07-02 06:41:16.622             bj = b[j]
2025-07-02 06:41:16.622             cruncher.set_seq2(bj)
2025-07-02 06:41:16.622             for i in range(alo, ahi):
2025-07-02 06:41:16.622                 ai = a[i]
2025-07-02 06:41:16.622                 if ai == bj:
2025-07-02 06:41:16.622                     if eqi is None:
2025-07-02 06:41:16.622                         eqi, eqj = i, j
2025-07-02 06:41:16.622                     continue
2025-07-02 06:41:16.622                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.622                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.622                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.623                 # compares by a factor of 3.
2025-07-02 06:41:16.623                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.623                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.623                 # of the computation is cached by cruncher
2025-07-02 06:41:16.623                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.623                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.623                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.623                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.623         if best_ratio < cutoff:
2025-07-02 06:41:16.623             # no non-identical "pretty close" pair
2025-07-02 06:41:16.623             if eqi is None:
2025-07-02 06:41:16.623                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.623                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.623                 return
2025-07-02 06:41:16.623             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.623             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.623         else:
2025-07-02 06:41:16.623             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.623             eqi = None
2025-07-02 06:41:16.623
2025-07-02 06:41:16.624         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.624         # identical
2025-07-02 06:41:16.624
2025-07-02 06:41:16.624         # pump out diffs from before the synch point
2025-07-02 06:41:16.624         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.624
2025-07-02 06:41:16.624         # do intraline marking on the synch pair
2025-07-02 06:41:16.624         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.624         if eqi is None:
2025-07-02 06:41:16.624             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.624             atags = btags = ""
2025-07-02 06:41:16.624             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.624             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.624                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.624                 if tag == 'replace':
2025-07-02 06:41:16.624                     atags += '^' * la
2025-07-02 06:41:16.624                     btags += '^' * lb
2025-07-02 06:41:16.624                 elif tag == 'delete':
2025-07-02 06:41:16.624                     atags += '-' * la
2025-07-02 06:41:16.625                 elif tag == 'insert':
2025-07-02 06:41:16.625                     btags += '+' * lb
2025-07-02 06:41:16.625                 elif tag == 'equal':
2025-07-02 06:41:16.625                     atags += ' ' * la
2025-07-02 06:41:16.625                     btags += ' ' * lb
2025-07-02 06:41:16.625                 else:
2025-07-02 06:41:16.625                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.625             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.625         else:
2025-07-02 06:41:16.625             # the synch pair is identical
2025-07-02 06:41:16.625             yield '  ' + aelt
2025-07-02 06:41:16.625
2025-07-02 06:41:16.625         # pump out diffs from after the synch point
2025-07-02 06:41:16.625 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.625
2025-07-02 06:41:16.625 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.625 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.625
2025-07-02 06:41:16.625 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.626 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.626 alo = 89, ahi = 1101
2025-07-02 06:41:16.626 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.626 blo = 89, bhi = 1101
2025-07-02 06:41:16.626
2025-07-02 06:41:16.626     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.626         g = []
2025-07-02 06:41:16.626         if alo < ahi:
2025-07-02 06:41:16.626             if blo < bhi:
2025-07-02 06:41:16.626                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.626             else:
2025-07-02 06:41:16.626                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.626         elif blo < bhi:
2025-07-02 06:41:16.626             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.626
2025-07-02 06:41:16.626 >       yield from g
2025-07-02 06:41:16.626
2025-07-02 06:41:16.626 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.627 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.627
2025-07-02 06:41:16.627 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.627 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.627 alo = 89, ahi = 1101
2025-07-02 06:41:16.627 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.627 blo = 89, bhi = 1101
2025-07-02 06:41:16.627
2025-07-02 06:41:16.627     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.627         r"""
2025-07-02 06:41:16.627         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.627         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.627         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.627         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.627
2025-07-02 06:41:16.627         Example:
2025-07-02 06:41:16.627
2025-07-02 06:41:16.627         >>> d = Differ()
2025-07-02 06:41:16.627         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.628         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.628         >>> print(''.join(results), end="")
2025-07-02 06:41:16.628         - abcDefghiJkl
2025-07-02 06:41:16.628         + abcdefGhijkl
2025-07-02 06:41:16.628         """
2025-07-02 06:41:16.628
2025-07-02 06:41:16.628         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.628         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.628         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.628         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.628         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.628
2025-07-02 06:41:16.628         # search for the pair that matches best without being identical
2025-07-02 06:41:16.628         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.628         # on junk -- unless we have to)
2025-07-02 06:41:16.628         for j in range(blo, bhi):
2025-07-02 06:41:16.628             bj = b[j]
2025-07-02 06:41:16.629             cruncher.set_seq2(bj)
2025-07-02 06:41:16.629             for i in range(alo, ahi):
2025-07-02 06:41:16.629                 ai = a[i]
2025-07-02 06:41:16.629                 if ai == bj:
2025-07-02 06:41:16.629                     if eqi is None:
2025-07-02 06:41:16.629                         eqi, eqj = i, j
2025-07-02 06:41:16.629                     continue
2025-07-02 06:41:16.629                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.629                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.629                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.629                 # compares by a factor of 3.
2025-07-02 06:41:16.629                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.629                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.629                 # of the computation is cached by cruncher
2025-07-02 06:41:16.629                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.629                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.629                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.629                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.629         if best_ratio < cutoff:
2025-07-02 06:41:16.630             # no non-identical "pretty close" pair
2025-07-02 06:41:16.630             if eqi is None:
2025-07-02 06:41:16.630                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.630                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.630                 return
2025-07-02 06:41:16.630             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.630             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.630         else:
2025-07-02 06:41:16.630             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.630             eqi = None
2025-07-02 06:41:16.630
2025-07-02 06:41:16.630         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.630         # identical
2025-07-02 06:41:16.630
2025-07-02 06:41:16.630         # pump out diffs from before the synch point
2025-07-02 06:41:16.630         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.630
2025-07-02 06:41:16.630         # do intraline marking on the synch pair
2025-07-02 06:41:16.630         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.630         if eqi is None:
2025-07-02 06:41:16.631             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.631             atags = btags = ""
2025-07-02 06:41:16.631             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.631             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.631                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.631                 if tag == 'replace':
2025-07-02 06:41:16.631                     atags += '^' * la
2025-07-02 06:41:16.631                     btags += '^' * lb
2025-07-02 06:41:16.631                 elif tag == 'delete':
2025-07-02 06:41:16.631                     atags += '-' * la
2025-07-02 06:41:16.631                 elif tag == 'insert':
2025-07-02 06:41:16.631                     btags += '+' * lb
2025-07-02 06:41:16.631                 elif tag == 'equal':
2025-07-02 06:41:16.631                     atags += ' ' * la
2025-07-02 06:41:16.631                     btags += ' ' * lb
2025-07-02 06:41:16.631                 else:
2025-07-02 06:41:16.631                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.631             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.631         else:
2025-07-02 06:41:16.631             # the synch pair is identical
2025-07-02 06:41:16.632             yield '  ' + aelt
2025-07-02 06:41:16.632
2025-07-02 06:41:16.632         # pump out diffs from after the synch point
2025-07-02 06:41:16.632 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.632
2025-07-02 06:41:16.632 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.632 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.632
2025-07-02 06:41:16.632 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.632 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.632 alo = 92, ahi = 1101
2025-07-02 06:41:16.632 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.632 blo = 92, bhi = 1101
2025-07-02 06:41:16.632
2025-07-02 06:41:16.632     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.632         g = []
2025-07-02 06:41:16.632         if alo < ahi:
2025-07-02 06:41:16.632             if blo < bhi:
2025-07-02 06:41:16.632                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.633             else:
2025-07-02 06:41:16.633                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.633         elif blo < bhi:
2025-07-02 06:41:16.633             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.633
2025-07-02 06:41:16.633 >       yield from g
2025-07-02 06:41:16.633
2025-07-02 06:41:16.633 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.633 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.633
2025-07-02 06:41:16.633 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.633 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.633 alo = 92, ahi = 1101
2025-07-02 06:41:16.633 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.633 blo = 92, bhi = 1101
2025-07-02 06:41:16.633
2025-07-02 06:41:16.633     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.633         r"""
2025-07-02 06:41:16.634         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.634         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.634         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.634         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.634
2025-07-02 06:41:16.634         Example:
2025-07-02 06:41:16.634
2025-07-02 06:41:16.634         >>> d = Differ()
2025-07-02 06:41:16.634         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.634         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.634         >>> print(''.join(results), end="")
2025-07-02 06:41:16.634         - abcDefghiJkl
2025-07-02 06:41:16.634         + abcdefGhijkl
2025-07-02 06:41:16.634         """
2025-07-02 06:41:16.634
2025-07-02 06:41:16.634         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.634         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.635         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.635         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.635         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.635
2025-07-02 06:41:16.635         # search for the pair that matches best without being identical
2025-07-02 06:41:16.635         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.635         # on junk -- unless we have to)
2025-07-02 06:41:16.635         for j in range(blo, bhi):
2025-07-02 06:41:16.635             bj = b[j]
2025-07-02 06:41:16.635             cruncher.set_seq2(bj)
2025-07-02 06:41:16.635             for i in range(alo, ahi):
2025-07-02 06:41:16.635                 ai = a[i]
2025-07-02 06:41:16.635                 if ai == bj:
2025-07-02 06:41:16.635                     if eqi is None:
2025-07-02 06:41:16.635                         eqi, eqj = i, j
2025-07-02 06:41:16.635                     continue
2025-07-02 06:41:16.635                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.635                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.635                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.636                 # compares by a factor of 3.
2025-07-02 06:41:16.636                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.636                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.636                 # of the computation is cached by cruncher
2025-07-02 06:41:16.636                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.636                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.636                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.636                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.636         if best_ratio < cutoff:
2025-07-02 06:41:16.636             # no non-identical "pretty close" pair
2025-07-02 06:41:16.636             if eqi is None:
2025-07-02 06:41:16.636                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.636                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.636                 return
2025-07-02 06:41:16.636             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.636             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.636         else:
2025-07-02 06:41:16.636             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.636             eqi = None
2025-07-02 06:41:16.637
2025-07-02 06:41:16.637         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.637         # identical
2025-07-02 06:41:16.637
2025-07-02 06:41:16.637         # pump out diffs from before the synch point
2025-07-02 06:41:16.637         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.637
2025-07-02 06:41:16.637         # do intraline marking on the synch pair
2025-07-02 06:41:16.637         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.637         if eqi is None:
2025-07-02 06:41:16.637             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.637             atags = btags = ""
2025-07-02 06:41:16.637             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.637             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.637                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.637                 if tag == 'replace':
2025-07-02 06:41:16.637                     atags += '^' * la
2025-07-02 06:41:16.637                     btags += '^' * lb
2025-07-02 06:41:16.637                 elif tag == 'delete':
2025-07-02 06:41:16.637                     atags += '-' * la
2025-07-02 06:41:16.638                 elif tag == 'insert':
2025-07-02 06:41:16.638                     btags += '+' * lb
2025-07-02 06:41:16.638                 elif tag == 'equal':
2025-07-02 06:41:16.638                     atags += ' ' * la
2025-07-02 06:41:16.638                     btags += ' ' * lb
2025-07-02 06:41:16.638                 else:
2025-07-02 06:41:16.638                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.638             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.638         else:
2025-07-02 06:41:16.638             # the synch pair is identical
2025-07-02 06:41:16.638             yield '  ' + aelt
2025-07-02 06:41:16.638
2025-07-02 06:41:16.638         # pump out diffs from after the synch point
2025-07-02 06:41:16.638 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.638
2025-07-02 06:41:16.638 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.638 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.638
2025-07-02 06:41:16.638 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.638 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.639 alo = 93, ahi = 1101
2025-07-02 06:41:16.639 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.639 blo = 93, bhi = 1101
2025-07-02 06:41:16.639
2025-07-02 06:41:16.639     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.639         g = []
2025-07-02 06:41:16.639         if alo < ahi:
2025-07-02 06:41:16.639             if blo < bhi:
2025-07-02 06:41:16.639                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.639             else:
2025-07-02 06:41:16.639                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.639         elif blo < bhi:
2025-07-02 06:41:16.639             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.639
2025-07-02 06:41:16.639 >       yield from g
2025-07-02 06:41:16.639
2025-07-02 06:41:16.639 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.639 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.639
2025-07-02 06:41:16.639 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.640 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.640 alo = 93, ahi = 1101
2025-07-02 06:41:16.640 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.640 blo = 93, bhi = 1101
2025-07-02 06:41:16.640
2025-07-02 06:41:16.640     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.640         r"""
2025-07-02 06:41:16.640         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.640         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.640         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.640         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.640
2025-07-02 06:41:16.640         Example:
2025-07-02 06:41:16.640
2025-07-02 06:41:16.640         >>> d = Differ()
2025-07-02 06:41:16.640         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.640         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.640         >>> print(''.join(results), end="")
2025-07-02 06:41:16.640         - abcDefghiJkl
2025-07-02 06:41:16.641         + abcdefGhijkl
2025-07-02 06:41:16.641         """
2025-07-02 06:41:16.641
2025-07-02 06:41:16.641         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.641         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.641         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.641         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.641         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.641
2025-07-02 06:41:16.641         # search for the pair that matches best without being identical
2025-07-02 06:41:16.641         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.641         # on junk -- unless we have to)
2025-07-02 06:41:16.641         for j in range(blo, bhi):
2025-07-02 06:41:16.641             bj = b[j]
2025-07-02 06:41:16.641             cruncher.set_seq2(bj)
2025-07-02 06:41:16.641             for i in range(alo, ahi):
2025-07-02 06:41:16.641                 ai = a[i]
2025-07-02 06:41:16.641                 if ai == bj:
2025-07-02 06:41:16.642                     if eqi is None:
2025-07-02 06:41:16.642                         eqi, eqj = i, j
2025-07-02 06:41:16.642                     continue
2025-07-02 06:41:16.642                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.642                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.642                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.642                 # compares by a factor of 3.
2025-07-02 06:41:16.642                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.642                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.642                 # of the computation is cached by cruncher
2025-07-02 06:41:16.642                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.642                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.642                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.642                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.642         if best_ratio < cutoff:
2025-07-02 06:41:16.642             # no non-identical "pretty close" pair
2025-07-02 06:41:16.642             if eqi is None:
2025-07-02 06:41:16.642                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.642                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.643                 return
2025-07-02 06:41:16.643             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.643             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.643         else:
2025-07-02 06:41:16.643             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.643             eqi = None
2025-07-02 06:41:16.643
2025-07-02 06:41:16.643         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.643         # identical
2025-07-02 06:41:16.643
2025-07-02 06:41:16.643         # pump out diffs from before the synch point
2025-07-02 06:41:16.643         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.643
2025-07-02 06:41:16.643         # do intraline marking on the synch pair
2025-07-02 06:41:16.643         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.643         if eqi is None:
2025-07-02 06:41:16.643             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.643             atags = btags = ""
2025-07-02 06:41:16.643             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.644             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.644                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.644                 if tag == 'replace':
2025-07-02 06:41:16.644                     atags += '^' * la
2025-07-02 06:41:16.644                     btags += '^' * lb
2025-07-02 06:41:16.644                 elif tag == 'delete':
2025-07-02 06:41:16.644                     atags += '-' * la
2025-07-02 06:41:16.644                 elif tag == 'insert':
2025-07-02 06:41:16.644                     btags += '+' * lb
2025-07-02 06:41:16.644                 elif tag == 'equal':
2025-07-02 06:41:16.644                     atags += ' ' * la
2025-07-02 06:41:16.644                     btags += ' ' * lb
2025-07-02 06:41:16.644                 else:
2025-07-02 06:41:16.644                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.644             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.644         else:
2025-07-02 06:41:16.644             # the synch pair is identical
2025-07-02 06:41:16.644             yield '  ' + aelt
2025-07-02 06:41:16.644
2025-07-02 06:41:16.645         # pump out diffs from after the synch point
2025-07-02 06:41:16.645 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.645
2025-07-02 06:41:16.645 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.645 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.645
2025-07-02 06:41:16.645 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.645 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.645 alo = 94, ahi = 1101
2025-07-02 06:41:16.645 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.645 blo = 94, bhi = 1101
2025-07-02 06:41:16.645
2025-07-02 06:41:16.645     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.645         g = []
2025-07-02 06:41:16.645         if alo < ahi:
2025-07-02 06:41:16.645             if blo < bhi:
2025-07-02 06:41:16.645                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.645             else:
2025-07-02 06:41:16.645                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.645         elif blo < bhi:
2025-07-02 06:41:16.646             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646 >       yield from g
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.646 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.646 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.646 alo = 94, ahi = 1101
2025-07-02 06:41:16.646 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.646 blo = 94, bhi = 1101
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.646         r"""
2025-07-02 06:41:16.646         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.646         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.646         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.646         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.646
2025-07-02 06:41:16.646         Example:
2025-07-02 06:41:16.647
2025-07-02 06:41:16.647         >>> d = Differ()
2025-07-02 06:41:16.647         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.647         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.647         >>> print(''.join(results), end="")
2025-07-02 06:41:16.647         - abcDefghiJkl
2025-07-02 06:41:16.647         + abcdefGhijkl
2025-07-02 06:41:16.647         """
2025-07-02 06:41:16.647
2025-07-02 06:41:16.647         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.647         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.647         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.647         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.647         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.647
2025-07-02 06:41:16.647         # search for the pair that matches best without being identical
2025-07-02 06:41:16.647         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.647         # on junk -- unless we have to)
2025-07-02 06:41:16.648         for j in range(blo, bhi):
2025-07-02 06:41:16.648             bj = b[j]
2025-07-02 06:41:16.648             cruncher.set_seq2(bj)
2025-07-02 06:41:16.648             for i in range(alo, ahi):
2025-07-02 06:41:16.648                 ai = a[i]
2025-07-02 06:41:16.648                 if ai == bj:
2025-07-02 06:41:16.648                     if eqi is None:
2025-07-02 06:41:16.648                         eqi, eqj = i, j
2025-07-02 06:41:16.648                     continue
2025-07-02 06:41:16.648                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.648                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.648                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.648                 # compares by a factor of 3.
2025-07-02 06:41:16.648                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.648                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.648                 # of the computation is cached by cruncher
2025-07-02 06:41:16.648                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.648                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.648                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.648                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.648         if best_ratio < cutoff:
2025-07-02 06:41:16.649             # no non-identical "pretty close" pair
2025-07-02 06:41:16.649             if eqi is None:
2025-07-02 06:41:16.649                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.649                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.649                 return
2025-07-02 06:41:16.649             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.649             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.649         else:
2025-07-02 06:41:16.649             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.649             eqi = None
2025-07-02 06:41:16.649
2025-07-02 06:41:16.649         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.649         # identical
2025-07-02 06:41:16.649
2025-07-02 06:41:16.649         # pump out diffs from before the synch point
2025-07-02 06:41:16.649         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.649
2025-07-02 06:41:16.650         # do intraline marking on the synch pair
2025-07-02 06:41:16.650         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.650         if eqi is None:
2025-07-02 06:41:16.650             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.650             atags = btags = ""
2025-07-02 06:41:16.650             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.650             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.650                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.650                 if tag == 'replace':
2025-07-02 06:41:16.650                     atags += '^' * la
2025-07-02 06:41:16.650                     btags += '^' * lb
2025-07-02 06:41:16.650                 elif tag == 'delete':
2025-07-02 06:41:16.650                     atags += '-' * la
2025-07-02 06:41:16.650                 elif tag == 'insert':
2025-07-02 06:41:16.650                     btags += '+' * lb
2025-07-02 06:41:16.650                 elif tag == 'equal':
2025-07-02 06:41:16.650                     atags += ' ' * la
2025-07-02 06:41:16.650                     btags += ' ' * lb
2025-07-02 06:41:16.650                 else:
2025-07-02 06:41:16.651                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.651             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.651         else:
2025-07-02 06:41:16.651             # the synch pair is identical
2025-07-02 06:41:16.651             yield '  ' + aelt
2025-07-02 06:41:16.651
2025-07-02 06:41:16.651         # pump out diffs from after the synch point
2025-07-02 06:41:16.651 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.651
2025-07-02 06:41:16.651 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.651 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.651
2025-07-02 06:41:16.651 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.651 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.651 alo = 95, ahi = 1101
2025-07-02 06:41:16.651 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.652 blo = 95, bhi = 1101
2025-07-02 06:41:16.652
2025-07-02 06:41:16.652     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.652         g = []
2025-07-02 06:41:16.652         if alo < ahi:
2025-07-02 06:41:16.652             if blo < bhi:
2025-07-02 06:41:16.652                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.652             else:
2025-07-02 06:41:16.652                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.652         elif blo < bhi:
2025-07-02 06:41:16.652             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.652
2025-07-02 06:41:16.652 >       yield from g
2025-07-02 06:41:16.652
2025-07-02 06:41:16.652 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.652 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.653
2025-07-02 06:41:16.653 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.653 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.653 alo = 95, ahi = 1101
2025-07-02 06:41:16.653 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.653 blo = 95, bhi = 1101
2025-07-02 06:41:16.653
2025-07-02 06:41:16.653     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.653         r"""
2025-07-02 06:41:16.653         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.653         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.653         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.653         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.653
2025-07-02 06:41:16.653         Example:
2025-07-02 06:41:16.653
2025-07-02 06:41:16.653         >>> d = Differ()
2025-07-02 06:41:16.654         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.654         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.654         >>> print(''.join(results), end="")
2025-07-02 06:41:16.654         - abcDefghiJkl
2025-07-02 06:41:16.654         + abcdefGhijkl
2025-07-02 06:41:16.654         """
2025-07-02 06:41:16.654
2025-07-02 06:41:16.654         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.654         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.654         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.654         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.654         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.654
2025-07-02 06:41:16.655         # search for the pair that matches best without being identical
2025-07-02 06:41:16.655         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.655         # on junk -- unless we have to)
2025-07-02 06:41:16.655         for j in range(blo, bhi):
2025-07-02 06:41:16.655             bj = b[j]
2025-07-02 06:41:16.655             cruncher.set_seq2(bj)
2025-07-02 06:41:16.655             for i in range(alo, ahi):
2025-07-02 06:41:16.655                 ai = a[i]
2025-07-02 06:41:16.655                 if ai == bj:
2025-07-02 06:41:16.655                     if eqi is None:
2025-07-02 06:41:16.655                         eqi, eqj = i, j
2025-07-02 06:41:16.655                     continue
2025-07-02 06:41:16.655                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.655                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.655                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.655                 # compares by a factor of 3.
2025-07-02 06:41:16.656                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.656                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.656                 # of the computation is cached by cruncher
2025-07-02 06:41:16.656                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.656                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.656                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.656                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.656         if best_ratio < cutoff:
2025-07-02 06:41:16.656             # no non-identical "pretty close" pair
2025-07-02 06:41:16.656             if eqi is None:
2025-07-02 06:41:16.656                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.656                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.656                 return
2025-07-02 06:41:16.656             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.656             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.656         else:
2025-07-02 06:41:16.657             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.657             eqi = None
2025-07-02 06:41:16.657
2025-07-02 06:41:16.657         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.657         # identical
2025-07-02 06:41:16.657
2025-07-02 06:41:16.657         # pump out diffs from before the synch point
2025-07-02 06:41:16.657         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.657
2025-07-02 06:41:16.657         # do intraline marking on the synch pair
2025-07-02 06:41:16.657         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.657         if eqi is None:
2025-07-02 06:41:16.657             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.657             atags = btags = ""
2025-07-02 06:41:16.657             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.657             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.658                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.658                 if tag == 'replace':
2025-07-02 06:41:16.658                     atags += '^' * la
2025-07-02 06:41:16.658                     btags += '^' * lb
2025-07-02 06:41:16.658                 elif tag == 'delete':
2025-07-02 06:41:16.658                     atags += '-' * la
2025-07-02 06:41:16.658                 elif tag == 'insert':
2025-07-02 06:41:16.658                     btags += '+' * lb
2025-07-02 06:41:16.658                 elif tag == 'equal':
2025-07-02 06:41:16.658                     atags += ' ' * la
2025-07-02 06:41:16.658                     btags += ' ' * lb
2025-07-02 06:41:16.658                 else:
2025-07-02 06:41:16.658                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.658             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.658         else:
2025-07-02 06:41:16.658             # the synch pair is identical
2025-07-02 06:41:16.658             yield '  ' + aelt
2025-07-02 06:41:16.659
2025-07-02 06:41:16.659         # pump out diffs from after the synch point
2025-07-02 06:41:16.659 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.659
2025-07-02 06:41:16.659 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.659 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.659
2025-07-02 06:41:16.659 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.659 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.659 alo = 96, ahi = 1101
2025-07-02 06:41:16.659 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.659 blo = 96, bhi = 1101
2025-07-02 06:41:16.659
2025-07-02 06:41:16.659     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.660         g = []
2025-07-02 06:41:16.660         if alo < ahi:
2025-07-02 06:41:16.660             if blo < bhi:
2025-07-02 06:41:16.660                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.660             else:
2025-07-02 06:41:16.660                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.660         elif blo < bhi:
2025-07-02 06:41:16.660             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.660
2025-07-02 06:41:16.660 >       yield from g
2025-07-02 06:41:16.660
2025-07-02 06:41:16.660 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.660 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.660
2025-07-02 06:41:16.660 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.660 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.661 alo = 96, ahi = 1101
2025-07-02 06:41:16.661 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.661 blo = 96, bhi = 1101
2025-07-02 06:41:16.661
2025-07-02 06:41:16.661     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.661         r"""
2025-07-02 06:41:16.661         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.661         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.661         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.661         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.661
2025-07-02 06:41:16.661         Example:
2025-07-02 06:41:16.661
2025-07-02 06:41:16.661         >>> d = Differ()
2025-07-02 06:41:16.661         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.661         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.662         >>> print(''.join(results), end="")
2025-07-02 06:41:16.662         - abcDefghiJkl
2025-07-02 06:41:16.662         + abcdefGhijkl
2025-07-02 06:41:16.662         """
2025-07-02 06:41:16.662
2025-07-02 06:41:16.662         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.662         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.662         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.662         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.662         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.662
2025-07-02 06:41:16.662         # search for the pair that matches best without being identical
2025-07-02 06:41:16.662         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.662         # on junk -- unless we have to)
2025-07-02 06:41:16.663         for j in range(blo, bhi):
2025-07-02 06:41:16.663             bj = b[j]
2025-07-02 06:41:16.663             cruncher.set_seq2(bj)
2025-07-02 06:41:16.663             for i in range(alo, ahi):
2025-07-02 06:41:16.663                 ai = a[i]
2025-07-02 06:41:16.663                 if ai == bj:
2025-07-02 06:41:16.663                     if eqi is None:
2025-07-02 06:41:16.663                         eqi, eqj = i, j
2025-07-02 06:41:16.663                     continue
2025-07-02 06:41:16.663                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.663                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.663                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.663                 # compares by a factor of 3.
2025-07-02 06:41:16.663                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.663                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.663                 # of the computation is cached by cruncher
2025-07-02 06:41:16.664                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.664                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.664                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.664                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.664         if best_ratio < cutoff:
2025-07-02 06:41:16.664             # no non-identical "pretty close" pair
2025-07-02 06:41:16.664             if eqi is None:
2025-07-02 06:41:16.664                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.664                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.664                 return
2025-07-02 06:41:16.664             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.664             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.664         else:
2025-07-02 06:41:16.664             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.664             eqi = None
2025-07-02 06:41:16.665
2025-07-02 06:41:16.665         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.665         # identical
2025-07-02 06:41:16.665
2025-07-02 06:41:16.665         # pump out diffs from before the synch point
2025-07-02 06:41:16.665         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.665
2025-07-02 06:41:16.665         # do intraline marking on the synch pair
2025-07-02 06:41:16.665         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.665         if eqi is None:
2025-07-02 06:41:16.665             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.665             atags = btags = ""
2025-07-02 06:41:16.665             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.665             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.665                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.665                 if tag == 'replace':
2025-07-02 06:41:16.666                     atags += '^' * la
2025-07-02 06:41:16.666                     btags += '^' * lb
2025-07-02 06:41:16.666                 elif tag == 'delete':
2025-07-02 06:41:16.666                     atags += '-' * la
2025-07-02 06:41:16.666                 elif tag == 'insert':
2025-07-02 06:41:16.666                     btags += '+' * lb
2025-07-02 06:41:16.666                 elif tag == 'equal':
2025-07-02 06:41:16.666                     atags += ' ' * la
2025-07-02 06:41:16.666                     btags += ' ' * lb
2025-07-02 06:41:16.666                 else:
2025-07-02 06:41:16.666                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.666             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.666         else:
2025-07-02 06:41:16.666             # the synch pair is identical
2025-07-02 06:41:16.666             yield '  ' + aelt
2025-07-02 06:41:16.666
2025-07-02 06:41:16.666         # pump out diffs from after the synch point
2025-07-02 06:41:16.667 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.667
2025-07-02 06:41:16.667 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.667 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.667
2025-07-02 06:41:16.667 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.667 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.667 alo = 97, ahi = 1101
2025-07-02 06:41:16.667 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.667 blo = 97, bhi = 1101
2025-07-02 06:41:16.667
2025-07-02 06:41:16.667     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.667         g = []
2025-07-02 06:41:16.667         if alo < ahi:
2025-07-02 06:41:16.668             if blo < bhi:
2025-07-02 06:41:16.668                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.668             else:
2025-07-02 06:41:16.668                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.668         elif blo < bhi:
2025-07-02 06:41:16.668             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.668
2025-07-02 06:41:16.668 >       yield from g
2025-07-02 06:41:16.668
2025-07-02 06:41:16.668 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.668 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.668
2025-07-02 06:41:16.668 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.668 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.668 alo = 97, ahi = 1101
2025-07-02 06:41:16.668 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.669 blo = 97, bhi = 1101
2025-07-02 06:41:16.669
2025-07-02 06:41:16.669     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.669         r"""
2025-07-02 06:41:16.669         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.669         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.669         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.669         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.669
2025-07-02 06:41:16.669         Example:
2025-07-02 06:41:16.669
2025-07-02 06:41:16.669         >>> d = Differ()
2025-07-02 06:41:16.669         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.669         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.669         >>> print(''.join(results), end="")
2025-07-02 06:41:16.669         - abcDefghiJkl
2025-07-02 06:41:16.670         + abcdefGhijkl
2025-07-02 06:41:16.670         """
2025-07-02 06:41:16.670
2025-07-02 06:41:16.670         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.670         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.670         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.670         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.670         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.670
2025-07-02 06:41:16.670         # search for the pair that matches best without being identical
2025-07-02 06:41:16.670         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.670         # on junk -- unless we have to)
2025-07-02 06:41:16.670         for j in range(blo, bhi):
2025-07-02 06:41:16.670             bj = b[j]
2025-07-02 06:41:16.671             cruncher.set_seq2(bj)
2025-07-02 06:41:16.671             for i in range(alo, ahi):
2025-07-02 06:41:16.671                 ai = a[i]
2025-07-02 06:41:16.671                 if ai == bj:
2025-07-02 06:41:16.671                     if eqi is None:
2025-07-02 06:41:16.671                         eqi, eqj = i, j
2025-07-02 06:41:16.671                     continue
2025-07-02 06:41:16.671                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.671                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.671                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.671                 # compares by a factor of 3.
2025-07-02 06:41:16.671                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.671                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.671                 # of the computation is cached by cruncher
2025-07-02 06:41:16.671                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.671                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.671                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.671                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.672         if best_ratio < cutoff:
2025-07-02 06:41:16.672             # no non-identical "pretty close" pair
2025-07-02 06:41:16.672             if eqi is None:
2025-07-02 06:41:16.672                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.672                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.672                 return
2025-07-02 06:41:16.672             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.672             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.672         else:
2025-07-02 06:41:16.672             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.672             eqi = None
2025-07-02 06:41:16.672
2025-07-02 06:41:16.672         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.672         # identical
2025-07-02 06:41:16.672
2025-07-02 06:41:16.672         # pump out diffs from before the synch point
2025-07-02 06:41:16.672         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.672
2025-07-02 06:41:16.672         # do intraline marking on the synch pair
2025-07-02 06:41:16.673         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.673         if eqi is None:
2025-07-02 06:41:16.673             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.673             atags = btags = ""
2025-07-02 06:41:16.673             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.673             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.673                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.673                 if tag == 'replace':
2025-07-02 06:41:16.673                     atags += '^' * la
2025-07-02 06:41:16.673                     btags += '^' * lb
2025-07-02 06:41:16.673                 elif tag == 'delete':
2025-07-02 06:41:16.673                     atags += '-' * la
2025-07-02 06:41:16.673                 elif tag == 'insert':
2025-07-02 06:41:16.673                     btags += '+' * lb
2025-07-02 06:41:16.673                 elif tag == 'equal':
2025-07-02 06:41:16.673                     atags += ' ' * la
2025-07-02 06:41:16.673                     btags += ' ' * lb
2025-07-02 06:41:16.673                 else:
2025-07-02 06:41:16.673                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.674             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.674         else:
2025-07-02 06:41:16.674             # the synch pair is identical
2025-07-02 06:41:16.674             yield '  ' + aelt
2025-07-02 06:41:16.674
2025-07-02 06:41:16.674         # pump out diffs from after the synch point
2025-07-02 06:41:16.674 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.674
2025-07-02 06:41:16.674 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.674 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.674
2025-07-02 06:41:16.674 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.674 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.674 alo = 98, ahi = 1101
2025-07-02 06:41:16.674 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.674 blo = 98, bhi = 1101
2025-07-02 06:41:16.674
2025-07-02 06:41:16.674     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.675         g = []
2025-07-02 06:41:16.675         if alo < ahi:
2025-07-02 06:41:16.675             if blo < bhi:
2025-07-02 06:41:16.675                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.675             else:
2025-07-02 06:41:16.675                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.675         elif blo < bhi:
2025-07-02 06:41:16.675             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.675
2025-07-02 06:41:16.675 >       yield from g
2025-07-02 06:41:16.675
2025-07-02 06:41:16.675 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.675 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.675
2025-07-02 06:41:16.675 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.675 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.675 alo = 98, ahi = 1101
2025-07-02 06:41:16.675 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.675 blo = 98, bhi = 1101
2025-07-02 06:41:16.675
2025-07-02 06:41:16.676     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.676         r"""
2025-07-02 06:41:16.676         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.676         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.676         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.676         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.676
2025-07-02 06:41:16.676         Example:
2025-07-02 06:41:16.676
2025-07-02 06:41:16.676         >>> d = Differ()
2025-07-02 06:41:16.676         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.676         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.676         >>> print(''.join(results), end="")
2025-07-02 06:41:16.676         - abcDefghiJkl
2025-07-02 06:41:16.676         + abcdefGhijkl
2025-07-02 06:41:16.676         """
2025-07-02 06:41:16.676
2025-07-02 06:41:16.677         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.677         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.677         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.677         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.677         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.677
2025-07-02 06:41:16.677         # search for the pair that matches best without being identical
2025-07-02 06:41:16.677         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.677         # on junk -- unless we have to)
2025-07-02 06:41:16.677         for j in range(blo, bhi):
2025-07-02 06:41:16.677             bj = b[j]
2025-07-02 06:41:16.677             cruncher.set_seq2(bj)
2025-07-02 06:41:16.677             for i in range(alo, ahi):
2025-07-02 06:41:16.677                 ai = a[i]
2025-07-02 06:41:16.677                 if ai == bj:
2025-07-02 06:41:16.677                     if eqi is None:
2025-07-02 06:41:16.677                         eqi, eqj = i, j
2025-07-02 06:41:16.677                     continue
2025-07-02 06:41:16.677                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.678                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.678                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.678                 # compares by a factor of 3.
2025-07-02 06:41:16.678                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.678                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.678                 # of the computation is cached by cruncher
2025-07-02 06:41:16.678                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.678                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.678                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.678                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.678         if best_ratio < cutoff:
2025-07-02 06:41:16.678             # no non-identical "pretty close" pair
2025-07-02 06:41:16.678             if eqi is None:
2025-07-02 06:41:16.678                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.678                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.678                 return
2025-07-02 06:41:16.678             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.678             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.678         else:
2025-07-02 06:41:16.679             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.679             eqi = None
2025-07-02 06:41:16.679
2025-07-02 06:41:16.679         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.679         # identical
2025-07-02 06:41:16.679
2025-07-02 06:41:16.679         # pump out diffs from before the synch point
2025-07-02 06:41:16.679         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.679
2025-07-02 06:41:16.679         # do intraline marking on the synch pair
2025-07-02 06:41:16.679         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.679         if eqi is None:
2025-07-02 06:41:16.679             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.679             atags = btags = ""
2025-07-02 06:41:16.679             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.679             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.679                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.679                 if tag == 'replace':
2025-07-02 06:41:16.679                     atags += '^' * la
2025-07-02 06:41:16.679                     btags += '^' * lb
2025-07-02 06:41:16.680                 elif tag == 'delete':
2025-07-02 06:41:16.680                     atags += '-' * la
2025-07-02 06:41:16.680                 elif tag == 'insert':
2025-07-02 06:41:16.680                     btags += '+' * lb
2025-07-02 06:41:16.680                 elif tag == 'equal':
2025-07-02 06:41:16.680                     atags += ' ' * la
2025-07-02 06:41:16.680                     btags += ' ' * lb
2025-07-02 06:41:16.680                 else:
2025-07-02 06:41:16.680                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.680             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.680         else:
2025-07-02 06:41:16.680             # the synch pair is identical
2025-07-02 06:41:16.680             yield '  ' + aelt
2025-07-02 06:41:16.680
2025-07-02 06:41:16.680         # pump out diffs from after the synch point
2025-07-02 06:41:16.680 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.680
2025-07-02 06:41:16.680 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.680 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.681
2025-07-02 06:41:16.681 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.681 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.681 alo = 99, ahi = 1101
2025-07-02 06:41:16.681 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.681 blo = 99, bhi = 1101
2025-07-02 06:41:16.681
2025-07-02 06:41:16.681     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.681         g = []
2025-07-02 06:41:16.681         if alo < ahi:
2025-07-02 06:41:16.681             if blo < bhi:
2025-07-02 06:41:16.681                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.681             else:
2025-07-02 06:41:16.681                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.681         elif blo < bhi:
2025-07-02 06:41:16.681             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.681
2025-07-02 06:41:16.681 >       yield from g
2025-07-02 06:41:16.681
2025-07-02 06:41:16.682 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.682 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.682
2025-07-02 06:41:16.682 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.682 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.682 alo = 99, ahi = 1101
2025-07-02 06:41:16.682 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.682 blo = 99, bhi = 1101
2025-07-02 06:41:16.682
2025-07-02 06:41:16.682     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.682         r"""
2025-07-02 06:41:16.682         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.682         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.682         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.682         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.682
2025-07-02 06:41:16.682         Example:
2025-07-02 06:41:16.683
2025-07-02 06:41:16.683         >>> d = Differ()
2025-07-02 06:41:16.683         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.683         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.683         >>> print(''.join(results), end="")
2025-07-02 06:41:16.683         - abcDefghiJkl
2025-07-02 06:41:16.683         + abcdefGhijkl
2025-07-02 06:41:16.683         """
2025-07-02 06:41:16.683
2025-07-02 06:41:16.683         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.683         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.683         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.683         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.683         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.683
2025-07-02 06:41:16.683         # search for the pair that matches best without being identical
2025-07-02 06:41:16.683         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.684         # on junk -- unless we have to)
2025-07-02 06:41:16.684         for j in range(blo, bhi):
2025-07-02 06:41:16.684             bj = b[j]
2025-07-02 06:41:16.684             cruncher.set_seq2(bj)
2025-07-02 06:41:16.684             for i in range(alo, ahi):
2025-07-02 06:41:16.684                 ai = a[i]
2025-07-02 06:41:16.684                 if ai == bj:
2025-07-02 06:41:16.684                     if eqi is None:
2025-07-02 06:41:16.684                         eqi, eqj = i, j
2025-07-02 06:41:16.684                     continue
2025-07-02 06:41:16.684                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.684                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.684                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.684                 # compares by a factor of 3.
2025-07-02 06:41:16.684                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.684                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.684                 # of the computation is cached by cruncher
2025-07-02 06:41:16.684                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.684                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.684                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.685                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.685         if best_ratio < cutoff:
2025-07-02 06:41:16.685             # no non-identical "pretty close" pair
2025-07-02 06:41:16.685             if eqi is None:
2025-07-02 06:41:16.685                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.685                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.685                 return
2025-07-02 06:41:16.685             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.685             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.685         else:
2025-07-02 06:41:16.685             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.685             eqi = None
2025-07-02 06:41:16.685
2025-07-02 06:41:16.685         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.685         # identical
2025-07-02 06:41:16.685
2025-07-02 06:41:16.685         # pump out diffs from before the synch point
2025-07-02 06:41:16.685         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.685
2025-07-02 06:41:16.686         # do intraline marking on the synch pair
2025-07-02 06:41:16.686         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.686         if eqi is None:
2025-07-02 06:41:16.686             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.686             atags = btags = ""
2025-07-02 06:41:16.686             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.686             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.686                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.686                 if tag == 'replace':
2025-07-02 06:41:16.686                     atags += '^' * la
2025-07-02 06:41:16.686                     btags += '^' * lb
2025-07-02 06:41:16.686                 elif tag == 'delete':
2025-07-02 06:41:16.686                     atags += '-' * la
2025-07-02 06:41:16.686                 elif tag == 'insert':
2025-07-02 06:41:16.686                     btags += '+' * lb
2025-07-02 06:41:16.686                 elif tag == 'equal':
2025-07-02 06:41:16.686                     atags += ' ' * la
2025-07-02 06:41:16.686                     btags += ' ' * lb
2025-07-02 06:41:16.686                 else:
2025-07-02 06:41:16.687                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.687             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.687         else:
2025-07-02 06:41:16.687             # the synch pair is identical
2025-07-02 06:41:16.687             yield '  ' + aelt
2025-07-02 06:41:16.687
2025-07-02 06:41:16.687         # pump out diffs from after the synch point
2025-07-02 06:41:16.687 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.687
2025-07-02 06:41:16.687 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.687 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.687
2025-07-02 06:41:16.687 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.687 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.687 alo = 100, ahi = 1101
2025-07-02 06:41:16.687 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.687 blo = 100, bhi = 1101
2025-07-02 06:41:16.687
2025-07-02 06:41:16.687     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.688         g = []
2025-07-02 06:41:16.688         if alo < ahi:
2025-07-02 06:41:16.688             if blo < bhi:
2025-07-02 06:41:16.688                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.688             else:
2025-07-02 06:41:16.688                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.688         elif blo < bhi:
2025-07-02 06:41:16.688             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.688
2025-07-02 06:41:16.688 >       yield from g
2025-07-02 06:41:16.688
2025-07-02 06:41:16.688 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.688 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.688
2025-07-02 06:41:16.688 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.688 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.688 alo = 100, ahi = 1101
2025-07-02 06:41:16.688 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.688 blo = 100, bhi = 1101
2025-07-02 06:41:16.688
2025-07-02 06:41:16.689     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.689         r"""
2025-07-02 06:41:16.689         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.689         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.689         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.689         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.689
2025-07-02 06:41:16.689         Example:
2025-07-02 06:41:16.689
2025-07-02 06:41:16.689         >>> d = Differ()
2025-07-02 06:41:16.689         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.689         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.689         >>> print(''.join(results), end="")
2025-07-02 06:41:16.689         - abcDefghiJkl
2025-07-02 06:41:16.689         + abcdefGhijkl
2025-07-02 06:41:16.689         """
2025-07-02 06:41:16.689
2025-07-02 06:41:16.690         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.690         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.690         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.690         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.690         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.690
2025-07-02 06:41:16.690         # search for the pair that matches best without being identical
2025-07-02 06:41:16.690         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.690         # on junk -- unless we have to)
2025-07-02 06:41:16.690         for j in range(blo, bhi):
2025-07-02 06:41:16.690             bj = b[j]
2025-07-02 06:41:16.690             cruncher.set_seq2(bj)
2025-07-02 06:41:16.690             for i in range(alo, ahi):
2025-07-02 06:41:16.690                 ai = a[i]
2025-07-02 06:41:16.690                 if ai == bj:
2025-07-02 06:41:16.690                     if eqi is None:
2025-07-02 06:41:16.690                         eqi, eqj = i, j
2025-07-02 06:41:16.690                     continue
2025-07-02 06:41:16.690                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.690                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.691                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.691                 # compares by a factor of 3.
2025-07-02 06:41:16.691                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.691                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.691                 # of the computation is cached by cruncher
2025-07-02 06:41:16.691                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.691                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.691                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.691                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.691         if best_ratio < cutoff:
2025-07-02 06:41:16.691             # no non-identical "pretty close" pair
2025-07-02 06:41:16.691             if eqi is None:
2025-07-02 06:41:16.691                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.691                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.691                 return
2025-07-02 06:41:16.691             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.691             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.691         else:
2025-07-02 06:41:16.691             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.692             eqi = None
2025-07-02 06:41:16.692
2025-07-02 06:41:16.692         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.692         # identical
2025-07-02 06:41:16.692
2025-07-02 06:41:16.692         # pump out diffs from before the synch point
2025-07-02 06:41:16.692         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.692
2025-07-02 06:41:16.692         # do intraline marking on the synch pair
2025-07-02 06:41:16.692         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.692         if eqi is None:
2025-07-02 06:41:16.692             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.692             atags = btags = ""
2025-07-02 06:41:16.692             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.692             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.692                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.692                 if tag == 'replace':
2025-07-02 06:41:16.692                     atags += '^' * la
2025-07-02 06:41:16.692                     btags += '^' * lb
2025-07-02 06:41:16.693                 elif tag == 'delete':
2025-07-02 06:41:16.693                     atags += '-' * la
2025-07-02 06:41:16.693                 elif tag == 'insert':
2025-07-02 06:41:16.693                     btags += '+' * lb
2025-07-02 06:41:16.693                 elif tag == 'equal':
2025-07-02 06:41:16.693                     atags += ' ' * la
2025-07-02 06:41:16.693                     btags += ' ' * lb
2025-07-02 06:41:16.693                 else:
2025-07-02 06:41:16.693                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.693             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.693         else:
2025-07-02 06:41:16.693             # the synch pair is identical
2025-07-02 06:41:16.693             yield '  ' + aelt
2025-07-02 06:41:16.693
2025-07-02 06:41:16.693         # pump out diffs from after the synch point
2025-07-02 06:41:16.693 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.693
2025-07-02 06:41:16.693 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.693 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.694
2025-07-02 06:41:16.694 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.694 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.694 alo = 101, ahi = 1101
2025-07-02 06:41:16.694 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.694 blo = 101, bhi = 1101
2025-07-02 06:41:16.694
2025-07-02 06:41:16.694     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.694         g = []
2025-07-02 06:41:16.694         if alo < ahi:
2025-07-02 06:41:16.694             if blo < bhi:
2025-07-02 06:41:16.694                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.694             else:
2025-07-02 06:41:16.694                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.694         elif blo < bhi:
2025-07-02 06:41:16.694             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.694
2025-07-02 06:41:16.694 >       yield from g
2025-07-02 06:41:16.694
2025-07-02 06:41:16.695 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.695 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.695
2025-07-02 06:41:16.695 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.695 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.695 alo = 101, ahi = 1101
2025-07-02 06:41:16.695 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.695 blo = 101, bhi = 1101
2025-07-02 06:41:16.695
2025-07-02 06:41:16.695     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.695         r"""
2025-07-02 06:41:16.695         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.695         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.695         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.695         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.695
2025-07-02 06:41:16.695         Example:
2025-07-02 06:41:16.695
2025-07-02 06:41:16.695         >>> d = Differ()
2025-07-02 06:41:16.696         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.696         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.696         >>> print(''.join(results), end="")
2025-07-02 06:41:16.696         - abcDefghiJkl
2025-07-02 06:41:16.696         + abcdefGhijkl
2025-07-02 06:41:16.696         """
2025-07-02 06:41:16.696
2025-07-02 06:41:16.696         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.696         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.696         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.696         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.696         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.696
2025-07-02 06:41:16.696         # search for the pair that matches best without being identical
2025-07-02 06:41:16.696         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.696         # on junk -- unless we have to)
2025-07-02 06:41:16.696         for j in range(blo, bhi):
2025-07-02 06:41:16.696             bj = b[j]
2025-07-02 06:41:16.697             cruncher.set_seq2(bj)
2025-07-02 06:41:16.697             for i in range(alo, ahi):
2025-07-02 06:41:16.697                 ai = a[i]
2025-07-02 06:41:16.697                 if ai == bj:
2025-07-02 06:41:16.697                     if eqi is None:
2025-07-02 06:41:16.697                         eqi, eqj = i, j
2025-07-02 06:41:16.697                     continue
2025-07-02 06:41:16.697                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.697                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.697                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.697                 # compares by a factor of 3.
2025-07-02 06:41:16.697                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.697                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.697                 # of the computation is cached by cruncher
2025-07-02 06:41:16.697                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.697                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.697                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.698                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.698         if best_ratio < cutoff:
2025-07-02 06:41:16.698             # no non-identical "pretty close" pair
2025-07-02 06:41:16.698             if eqi is None:
2025-07-02 06:41:16.698                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.698                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.698                 return
2025-07-02 06:41:16.698             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.698             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.698         else:
2025-07-02 06:41:16.698             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.698             eqi = None
2025-07-02 06:41:16.698
2025-07-02 06:41:16.698         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.698         # identical
2025-07-02 06:41:16.698
2025-07-02 06:41:16.698         # pump out diffs from before the synch point
2025-07-02 06:41:16.698         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.698
2025-07-02 06:41:16.699         # do intraline marking on the synch pair
2025-07-02 06:41:16.699         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.699         if eqi is None:
2025-07-02 06:41:16.699             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.699             atags = btags = ""
2025-07-02 06:41:16.699             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.699             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.699                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.699                 if tag == 'replace':
2025-07-02 06:41:16.699                     atags += '^' * la
2025-07-02 06:41:16.699                     btags += '^' * lb
2025-07-02 06:41:16.699                 elif tag == 'delete':
2025-07-02 06:41:16.699                     atags += '-' * la
2025-07-02 06:41:16.699                 elif tag == 'insert':
2025-07-02 06:41:16.699                     btags += '+' * lb
2025-07-02 06:41:16.699                 elif tag == 'equal':
2025-07-02 06:41:16.699                     atags += ' ' * la
2025-07-02 06:41:16.699                     btags += ' ' * lb
2025-07-02 06:41:16.699                 else:
2025-07-02 06:41:16.699                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.700             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.700         else:
2025-07-02 06:41:16.700             # the synch pair is identical
2025-07-02 06:41:16.700             yield '  ' + aelt
2025-07-02 06:41:16.700
2025-07-02 06:41:16.700         # pump out diffs from after the synch point
2025-07-02 06:41:16.700 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.700
2025-07-02 06:41:16.700 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.700 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.700
2025-07-02 06:41:16.700 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.700 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.700 alo = 102, ahi = 1101
2025-07-02 06:41:16.700 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.700 blo = 102, bhi = 1101
2025-07-02 06:41:16.700
2025-07-02 06:41:16.700     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.701         g = []
2025-07-02 06:41:16.701         if alo < ahi:
2025-07-02 06:41:16.701             if blo < bhi:
2025-07-02 06:41:16.701                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.701             else:
2025-07-02 06:41:16.701                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.701         elif blo < bhi:
2025-07-02 06:41:16.701             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.701
2025-07-02 06:41:16.701 >       yield from g
2025-07-02 06:41:16.701
2025-07-02 06:41:16.701 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.701 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.701
2025-07-02 06:41:16.701 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.701 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.701 alo = 102, ahi = 1101
2025-07-02 06:41:16.701 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.701 blo = 102, bhi = 1101
2025-07-02 06:41:16.702
2025-07-02 06:41:16.702     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.702         r"""
2025-07-02 06:41:16.702         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.702         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.702         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.702         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.702
2025-07-02 06:41:16.702         Example:
2025-07-02 06:41:16.702
2025-07-02 06:41:16.702         >>> d = Differ()
2025-07-02 06:41:16.702         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.702         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.702         >>> print(''.join(results), end="")
2025-07-02 06:41:16.702         - abcDefghiJkl
2025-07-02 06:41:16.702         + abcdefGhijkl
2025-07-02 06:41:16.702         """
2025-07-02 06:41:16.702
2025-07-02 06:41:16.703         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.703         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.703         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.703         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.703         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.703
2025-07-02 06:41:16.703         # search for the pair that matches best without being identical
2025-07-02 06:41:16.703         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.703         # on junk -- unless we have to)
2025-07-02 06:41:16.703         for j in range(blo, bhi):
2025-07-02 06:41:16.703             bj = b[j]
2025-07-02 06:41:16.703             cruncher.set_seq2(bj)
2025-07-02 06:41:16.703             for i in range(alo, ahi):
2025-07-02 06:41:16.703                 ai = a[i]
2025-07-02 06:41:16.703                 if ai == bj:
2025-07-02 06:41:16.703                     if eqi is None:
2025-07-02 06:41:16.703                         eqi, eqj = i, j
2025-07-02 06:41:16.703                     continue
2025-07-02 06:41:16.703                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.703                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.704                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.704                 # compares by a factor of 3.
2025-07-02 06:41:16.704                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.704                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.704                 # of the computation is cached by cruncher
2025-07-02 06:41:16.704                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.704                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.704                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.704                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.704         if best_ratio < cutoff:
2025-07-02 06:41:16.704             # no non-identical "pretty close" pair
2025-07-02 06:41:16.704             if eqi is None:
2025-07-02 06:41:16.704                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.704                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.704                 return
2025-07-02 06:41:16.704             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.704             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.704         else:
2025-07-02 06:41:16.704             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.705             eqi = None
2025-07-02 06:41:16.705
2025-07-02 06:41:16.705         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.705         # identical
2025-07-02 06:41:16.705
2025-07-02 06:41:16.705         # pump out diffs from before the synch point
2025-07-02 06:41:16.705         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.705
2025-07-02 06:41:16.705         # do intraline marking on the synch pair
2025-07-02 06:41:16.705         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.705         if eqi is None:
2025-07-02 06:41:16.705             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.705             atags = btags = ""
2025-07-02 06:41:16.705             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.705             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.705                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.705                 if tag == 'replace':
2025-07-02 06:41:16.705                     atags += '^' * la
2025-07-02 06:41:16.705                     btags += '^' * lb
2025-07-02 06:41:16.706                 elif tag == 'delete':
2025-07-02 06:41:16.706                     atags += '-' * la
2025-07-02 06:41:16.706                 elif tag == 'insert':
2025-07-02 06:41:16.706                     btags += '+' * lb
2025-07-02 06:41:16.706                 elif tag == 'equal':
2025-07-02 06:41:16.706                     atags += ' ' * la
2025-07-02 06:41:16.706                     btags += ' ' * lb
2025-07-02 06:41:16.706                 else:
2025-07-02 06:41:16.706                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.706             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.706         else:
2025-07-02 06:41:16.706             # the synch pair is identical
2025-07-02 06:41:16.706             yield '  ' + aelt
2025-07-02 06:41:16.706
2025-07-02 06:41:16.706         # pump out diffs from after the synch point
2025-07-02 06:41:16.706 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.706
2025-07-02 06:41:16.706 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.706 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.706
2025-07-02 06:41:16.707 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.707 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.707 alo = 103, ahi = 1101
2025-07-02 06:41:16.707 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.707 blo = 103, bhi = 1101
2025-07-02 06:41:16.707
2025-07-02 06:41:16.707     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.707         g = []
2025-07-02 06:41:16.707         if alo < ahi:
2025-07-02 06:41:16.707             if blo < bhi:
2025-07-02 06:41:16.707                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.707             else:
2025-07-02 06:41:16.707                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.707         elif blo < bhi:
2025-07-02 06:41:16.707             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.707
2025-07-02 06:41:16.707 >       yield from g
2025-07-02 06:41:16.707
2025-07-02 06:41:16.707 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.708 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.708
2025-07-02 06:41:16.708 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.708 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.708 alo = 103, ahi = 1101
2025-07-02 06:41:16.708 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.708 blo = 103, bhi = 1101
2025-07-02 06:41:16.708
2025-07-02 06:41:16.708     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.708         r"""
2025-07-02 06:41:16.708         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.708         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.708         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.708         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.708
2025-07-02 06:41:16.708         Example:
2025-07-02 06:41:16.708
2025-07-02 06:41:16.708         >>> d = Differ()
2025-07-02 06:41:16.708         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.709         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.709         >>> print(''.join(results), end="")
2025-07-02 06:41:16.709         - abcDefghiJkl
2025-07-02 06:41:16.709         + abcdefGhijkl
2025-07-02 06:41:16.709         """
2025-07-02 06:41:16.709
2025-07-02 06:41:16.709         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.709         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.709         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.709         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.709         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.709
2025-07-02 06:41:16.709         # search for the pair that matches best without being identical
2025-07-02 06:41:16.709         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.709         # on junk -- unless we have to)
2025-07-02 06:41:16.709         for j in range(blo, bhi):
2025-07-02 06:41:16.709             bj = b[j]
2025-07-02 06:41:16.710             cruncher.set_seq2(bj)
2025-07-02 06:41:16.710             for i in range(alo, ahi):
2025-07-02 06:41:16.710                 ai = a[i]
2025-07-02 06:41:16.710                 if ai == bj:
2025-07-02 06:41:16.710                     if eqi is None:
2025-07-02 06:41:16.710                         eqi, eqj = i, j
2025-07-02 06:41:16.710                     continue
2025-07-02 06:41:16.710                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.710                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.710                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.710                 # compares by a factor of 3.
2025-07-02 06:41:16.710                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.710                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.710                 # of the computation is cached by cruncher
2025-07-02 06:41:16.710                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.710                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.710                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.710                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.710         if best_ratio < cutoff:
2025-07-02 06:41:16.711             # no non-identical "pretty close" pair
2025-07-02 06:41:16.711             if eqi is None:
2025-07-02 06:41:16.711                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.711                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.711                 return
2025-07-02 06:41:16.711             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.711             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.711         else:
2025-07-02 06:41:16.711             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.711             eqi = None
2025-07-02 06:41:16.711
2025-07-02 06:41:16.711         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.711         # identical
2025-07-02 06:41:16.711
2025-07-02 06:41:16.711         # pump out diffs from before the synch point
2025-07-02 06:41:16.711         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.711
2025-07-02 06:41:16.711         # do intraline marking on the synch pair
2025-07-02 06:41:16.711         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.712         if eqi is None:
2025-07-02 06:41:16.712             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.712             atags = btags = ""
2025-07-02 06:41:16.712             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.712             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.712                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.712                 if tag == 'replace':
2025-07-02 06:41:16.712                     atags += '^' * la
2025-07-02 06:41:16.712                     btags += '^' * lb
2025-07-02 06:41:16.712                 elif tag == 'delete':
2025-07-02 06:41:16.712                     atags += '-' * la
2025-07-02 06:41:16.712                 elif tag == 'insert':
2025-07-02 06:41:16.712                     btags += '+' * lb
2025-07-02 06:41:16.712                 elif tag == 'equal':
2025-07-02 06:41:16.712                     atags += ' ' * la
2025-07-02 06:41:16.712                     btags += ' ' * lb
2025-07-02 06:41:16.712                 else:
2025-07-02 06:41:16.712                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.712             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.712         else:
2025-07-02 06:41:16.713             # the synch pair is identical
2025-07-02 06:41:16.713             yield '  ' + aelt
2025-07-02 06:41:16.713
2025-07-02 06:41:16.713         # pump out diffs from after the synch point
2025-07-02 06:41:16.713 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.713
2025-07-02 06:41:16.713 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.713 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.713
2025-07-02 06:41:16.713 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.713 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.713 alo = 104, ahi = 1101
2025-07-02 06:41:16.713 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.713 blo = 104, bhi = 1101
2025-07-02 06:41:16.713
2025-07-02 06:41:16.713     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.714         g = []
2025-07-02 06:41:16.714         if alo < ahi:
2025-07-02 06:41:16.714             if blo < bhi:
2025-07-02 06:41:16.714                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.714             else:
2025-07-02 06:41:16.714                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.714         elif blo < bhi:
2025-07-02 06:41:16.714             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.714
2025-07-02 06:41:16.714 >       yield from g
2025-07-02 06:41:16.714
2025-07-02 06:41:16.714 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.714 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.714
2025-07-02 06:41:16.714 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.714 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.714 alo = 104, ahi = 1101
2025-07-02 06:41:16.714 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.714 blo = 104, bhi = 1101
2025-07-02 06:41:16.714
2025-07-02 06:41:16.715     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.715         r"""
2025-07-02 06:41:16.715         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.715         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.715         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.715         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.715
2025-07-02 06:41:16.715         Example:
2025-07-02 06:41:16.715
2025-07-02 06:41:16.715         >>> d = Differ()
2025-07-02 06:41:16.715         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.715         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.715         >>> print(''.join(results), end="")
2025-07-02 06:41:16.715         - abcDefghiJkl
2025-07-02 06:41:16.715         + abcdefGhijkl
2025-07-02 06:41:16.715         """
2025-07-02 06:41:16.715
2025-07-02 06:41:16.716         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.716         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.716         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.716         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.716         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.716
2025-07-02 06:41:16.716         # search for the pair that matches best without being identical
2025-07-02 06:41:16.716         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.716         # on junk -- unless we have to)
2025-07-02 06:41:16.716         for j in range(blo, bhi):
2025-07-02 06:41:16.716             bj = b[j]
2025-07-02 06:41:16.716             cruncher.set_seq2(bj)
2025-07-02 06:41:16.716             for i in range(alo, ahi):
2025-07-02 06:41:16.716                 ai = a[i]
2025-07-02 06:41:16.716                 if ai == bj:
2025-07-02 06:41:16.716                     if eqi is None:
2025-07-02 06:41:16.716                         eqi, eqj = i, j
2025-07-02 06:41:16.716                     continue
2025-07-02 06:41:16.716                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.716                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.717                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.717                 # compares by a factor of 3.
2025-07-02 06:41:16.717                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.717                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.717                 # of the computation is cached by cruncher
2025-07-02 06:41:16.717                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.717                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.717                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.717                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.717         if best_ratio < cutoff:
2025-07-02 06:41:16.717             # no non-identical "pretty close" pair
2025-07-02 06:41:16.717             if eqi is None:
2025-07-02 06:41:16.717                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.717                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.717                 return
2025-07-02 06:41:16.717             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.717             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.717         else:
2025-07-02 06:41:16.717             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.718             eqi = None
2025-07-02 06:41:16.718
2025-07-02 06:41:16.718         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.718         # identical
2025-07-02 06:41:16.718
2025-07-02 06:41:16.718         # pump out diffs from before the synch point
2025-07-02 06:41:16.718         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.718
2025-07-02 06:41:16.718         # do intraline marking on the synch pair
2025-07-02 06:41:16.718         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.718         if eqi is None:
2025-07-02 06:41:16.718             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.718             atags = btags = ""
2025-07-02 06:41:16.718             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.718             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.718                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.718                 if tag == 'replace':
2025-07-02 06:41:16.718                     atags += '^' * la
2025-07-02 06:41:16.718                     btags += '^' * lb
2025-07-02 06:41:16.719                 elif tag == 'delete':
2025-07-02 06:41:16.719                     atags += '-' * la
2025-07-02 06:41:16.719                 elif tag == 'insert':
2025-07-02 06:41:16.719                     btags += '+' * lb
2025-07-02 06:41:16.719                 elif tag == 'equal':
2025-07-02 06:41:16.719                     atags += ' ' * la
2025-07-02 06:41:16.719                     btags += ' ' * lb
2025-07-02 06:41:16.719                 else:
2025-07-02 06:41:16.719                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.719             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.719         else:
2025-07-02 06:41:16.719             # the synch pair is identical
2025-07-02 06:41:16.719             yield '  ' + aelt
2025-07-02 06:41:16.719
2025-07-02 06:41:16.719         # pump out diffs from after the synch point
2025-07-02 06:41:16.719 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.719
2025-07-02 06:41:16.719 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.719 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.720
2025-07-02 06:41:16.720 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.720 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.720 alo = 105, ahi = 1101
2025-07-02 06:41:16.720 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.720 blo = 105, bhi = 1101
2025-07-02 06:41:16.720
2025-07-02 06:41:16.720     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.720         g = []
2025-07-02 06:41:16.720         if alo < ahi:
2025-07-02 06:41:16.720             if blo < bhi:
2025-07-02 06:41:16.720                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.720             else:
2025-07-02 06:41:16.720                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.720         elif blo < bhi:
2025-07-02 06:41:16.720             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.720
2025-07-02 06:41:16.720 >       yield from g
2025-07-02 06:41:16.720
2025-07-02 06:41:16.720 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.721 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.721
2025-07-02 06:41:16.721 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.721 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.721 alo = 105, ahi = 1101
2025-07-02 06:41:16.721 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.721 blo = 105, bhi = 1101
2025-07-02 06:41:16.721
2025-07-02 06:41:16.721     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.721         r"""
2025-07-02 06:41:16.721         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.721         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.721         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.721         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.721
2025-07-02 06:41:16.721         Example:
2025-07-02 06:41:16.721
2025-07-02 06:41:16.722         >>> d = Differ()
2025-07-02 06:41:16.722         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.722         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.722         >>> print(''.join(results), end="")
2025-07-02 06:41:16.722         - abcDefghiJkl
2025-07-02 06:41:16.722         + abcdefGhijkl
2025-07-02 06:41:16.722         """
2025-07-02 06:41:16.722
2025-07-02 06:41:16.722         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.722         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.722         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.722         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.722         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.722
2025-07-02 06:41:16.722         # search for the pair that matches best without being identical
2025-07-02 06:41:16.722         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.722         # on junk -- unless we have to)
2025-07-02 06:41:16.723         for j in range(blo, bhi):
2025-07-02 06:41:16.723             bj = b[j]
2025-07-02 06:41:16.723             cruncher.set_seq2(bj)
2025-07-02 06:41:16.723             for i in range(alo, ahi):
2025-07-02 06:41:16.723                 ai = a[i]
2025-07-02 06:41:16.723                 if ai == bj:
2025-07-02 06:41:16.723                     if eqi is None:
2025-07-02 06:41:16.723                         eqi, eqj = i, j
2025-07-02 06:41:16.723                     continue
2025-07-02 06:41:16.723                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.723                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.723                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.723                 # compares by a factor of 3.
2025-07-02 06:41:16.723                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.723                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.723                 # of the computation is cached by cruncher
2025-07-02 06:41:16.723                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.723                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.723                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.724                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.724         if best_ratio < cutoff:
2025-07-02 06:41:16.724             # no non-identical "pretty close" pair
2025-07-02 06:41:16.724             if eqi is None:
2025-07-02 06:41:16.724                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.724                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.724                 return
2025-07-02 06:41:16.724             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.724             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.724         else:
2025-07-02 06:41:16.724             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.724             eqi = None
2025-07-02 06:41:16.724
2025-07-02 06:41:16.724         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.724         # identical
2025-07-02 06:41:16.724
2025-07-02 06:41:16.724         # pump out diffs from before the synch point
2025-07-02 06:41:16.724         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.724
2025-07-02 06:41:16.724         # do intraline marking on the synch pair
2025-07-02 06:41:16.725         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.725         if eqi is None:
2025-07-02 06:41:16.725             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.725             atags = btags = ""
2025-07-02 06:41:16.725             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.725             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.725                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.725                 if tag == 'replace':
2025-07-02 06:41:16.725                     atags += '^' * la
2025-07-02 06:41:16.725                     btags += '^' * lb
2025-07-02 06:41:16.725                 elif tag == 'delete':
2025-07-02 06:41:16.725                     atags += '-' * la
2025-07-02 06:41:16.725                 elif tag == 'insert':
2025-07-02 06:41:16.725                     btags += '+' * lb
2025-07-02 06:41:16.725                 elif tag == 'equal':
2025-07-02 06:41:16.725                     atags += ' ' * la
2025-07-02 06:41:16.725                     btags += ' ' * lb
2025-07-02 06:41:16.725                 else:
2025-07-02 06:41:16.725                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.726             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.726         else:
2025-07-02 06:41:16.726             # the synch pair is identical
2025-07-02 06:41:16.726             yield '  ' + aelt
2025-07-02 06:41:16.726
2025-07-02 06:41:16.726         # pump out diffs from after the synch point
2025-07-02 06:41:16.726 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.726
2025-07-02 06:41:16.726 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.726 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.726
2025-07-02 06:41:16.726 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.726 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.726 alo = 106, ahi = 1101
2025-07-02 06:41:16.726 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.726 blo = 106, bhi = 1101
2025-07-02 06:41:16.726
2025-07-02 06:41:16.726     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.726         g = []
2025-07-02 06:41:16.727         if alo < ahi:
2025-07-02 06:41:16.727             if blo < bhi:
2025-07-02 06:41:16.727                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.727             else:
2025-07-02 06:41:16.727                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.727         elif blo < bhi:
2025-07-02 06:41:16.727             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.727
2025-07-02 06:41:16.727 >       yield from g
2025-07-02 06:41:16.727
2025-07-02 06:41:16.727 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.727 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.727
2025-07-02 06:41:16.727 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.727 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.727 alo = 106, ahi = 1101
2025-07-02 06:41:16.727 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.727 blo = 106, bhi = 1101
2025-07-02 06:41:16.728
2025-07-02 06:41:16.728     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.728         r"""
2025-07-02 06:41:16.728         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.728         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.728         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.728         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.728
2025-07-02 06:41:16.728         Example:
2025-07-02 06:41:16.728
2025-07-02 06:41:16.728         >>> d = Differ()
2025-07-02 06:41:16.728         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.728         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.728         >>> print(''.join(results), end="")
2025-07-02 06:41:16.728         - abcDefghiJkl
2025-07-02 06:41:16.728         + abcdefGhijkl
2025-07-02 06:41:16.728         """
2025-07-02 06:41:16.728
2025-07-02 06:41:16.728         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.729         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.729         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.729         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.729         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.729
2025-07-02 06:41:16.729         # search for the pair that matches best without being identical
2025-07-02 06:41:16.729         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.729         # on junk -- unless we have to)
2025-07-02 06:41:16.729         for j in range(blo, bhi):
2025-07-02 06:41:16.729             bj = b[j]
2025-07-02 06:41:16.729             cruncher.set_seq2(bj)
2025-07-02 06:41:16.729             for i in range(alo, ahi):
2025-07-02 06:41:16.729                 ai = a[i]
2025-07-02 06:41:16.729                 if ai == bj:
2025-07-02 06:41:16.729                     if eqi is None:
2025-07-02 06:41:16.729                         eqi, eqj = i, j
2025-07-02 06:41:16.729                     continue
2025-07-02 06:41:16.729                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.730                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.730                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.730                 # compares by a factor of 3.
2025-07-02 06:41:16.730                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.730                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.730                 # of the computation is cached by cruncher
2025-07-02 06:41:16.730                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.730                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.730                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.730                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.730         if best_ratio < cutoff:
2025-07-02 06:41:16.730             # no non-identical "pretty close" pair
2025-07-02 06:41:16.730             if eqi is None:
2025-07-02 06:41:16.730                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.730                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.730                 return
2025-07-02 06:41:16.730             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.730             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.730         else:
2025-07-02 06:41:16.731             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.731             eqi = None
2025-07-02 06:41:16.731
2025-07-02 06:41:16.731         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.731         # identical
2025-07-02 06:41:16.731
2025-07-02 06:41:16.731         # pump out diffs from before the synch point
2025-07-02 06:41:16.731         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.731
2025-07-02 06:41:16.731         # do intraline marking on the synch pair
2025-07-02 06:41:16.731         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.731         if eqi is None:
2025-07-02 06:41:16.731             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.731             atags = btags = ""
2025-07-02 06:41:16.731             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.731             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.731                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.731                 if tag == 'replace':
2025-07-02 06:41:16.731                     atags += '^' * la
2025-07-02 06:41:16.731                     btags += '^' * lb
2025-07-02 06:41:16.732                 elif tag == 'delete':
2025-07-02 06:41:16.732                     atags += '-' * la
2025-07-02 06:41:16.732                 elif tag == 'insert':
2025-07-02 06:41:16.732                     btags += '+' * lb
2025-07-02 06:41:16.732                 elif tag == 'equal':
2025-07-02 06:41:16.732                     atags += ' ' * la
2025-07-02 06:41:16.732                     btags += ' ' * lb
2025-07-02 06:41:16.732                 else:
2025-07-02 06:41:16.732                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.732             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.732         else:
2025-07-02 06:41:16.732             # the synch pair is identical
2025-07-02 06:41:16.732             yield '  ' + aelt
2025-07-02 06:41:16.732
2025-07-02 06:41:16.732         # pump out diffs from after the synch point
2025-07-02 06:41:16.732 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.732
2025-07-02 06:41:16.732 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.732 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.733
2025-07-02 06:41:16.733 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.733 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.733 alo = 107, ahi = 1101
2025-07-02 06:41:16.733 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.733 blo = 107, bhi = 1101
2025-07-02 06:41:16.733
2025-07-02 06:41:16.733     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.733         g = []
2025-07-02 06:41:16.733         if alo < ahi:
2025-07-02 06:41:16.733             if blo < bhi:
2025-07-02 06:41:16.733                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.733             else:
2025-07-02 06:41:16.733                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.733         elif blo < bhi:
2025-07-02 06:41:16.733             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.733
2025-07-02 06:41:16.733 >       yield from g
2025-07-02 06:41:16.733
2025-07-02 06:41:16.734 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.734 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.734
2025-07-02 06:41:16.734 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.734 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.734 alo = 107, ahi = 1101
2025-07-02 06:41:16.734 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.734 blo = 107, bhi = 1101
2025-07-02 06:41:16.734
2025-07-02 06:41:16.734     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.734         r"""
2025-07-02 06:41:16.734         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.734         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.734         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.734         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.734
2025-07-02 06:41:16.734         Example:
2025-07-02 06:41:16.734
2025-07-02 06:41:16.734         >>> d = Differ()
2025-07-02 06:41:16.735         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.735         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.735         >>> print(''.join(results), end="")
2025-07-02 06:41:16.735         - abcDefghiJkl
2025-07-02 06:41:16.735         + abcdefGhijkl
2025-07-02 06:41:16.735         """
2025-07-02 06:41:16.735
2025-07-02 06:41:16.735         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.735         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.735         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.735         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.735         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.735
2025-07-02 06:41:16.735         # search for the pair that matches best without being identical
2025-07-02 06:41:16.735         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.735         # on junk -- unless we have to)
2025-07-02 06:41:16.735         for j in range(blo, bhi):
2025-07-02 06:41:16.735             bj = b[j]
2025-07-02 06:41:16.736             cruncher.set_seq2(bj)
2025-07-02 06:41:16.736             for i in range(alo, ahi):
2025-07-02 06:41:16.736                 ai = a[i]
2025-07-02 06:41:16.736                 if ai == bj:
2025-07-02 06:41:16.736                     if eqi is None:
2025-07-02 06:41:16.736                         eqi, eqj = i, j
2025-07-02 06:41:16.736                     continue
2025-07-02 06:41:16.736                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.736                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.736                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.736                 # compares by a factor of 3.
2025-07-02 06:41:16.736                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.736                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.736                 # of the computation is cached by cruncher
2025-07-02 06:41:16.736                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.736                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.736                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.736                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.736         if best_ratio < cutoff:
2025-07-02 06:41:16.737             # no non-identical "pretty close" pair
2025-07-02 06:41:16.737             if eqi is None:
2025-07-02 06:41:16.737                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.737                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.737                 return
2025-07-02 06:41:16.737             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.737             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.737         else:
2025-07-02 06:41:16.737             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.737             eqi = None
2025-07-02 06:41:16.737
2025-07-02 06:41:16.737         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.737         # identical
2025-07-02 06:41:16.737
2025-07-02 06:41:16.737         # pump out diffs from before the synch point
2025-07-02 06:41:16.737         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.737
2025-07-02 06:41:16.737         # do intraline marking on the synch pair
2025-07-02 06:41:16.737         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.737         if eqi is None:
2025-07-02 06:41:16.738             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.738             atags = btags = ""
2025-07-02 06:41:16.738             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.738             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.738                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.738                 if tag == 'replace':
2025-07-02 06:41:16.738                     atags += '^' * la
2025-07-02 06:41:16.738                     btags += '^' * lb
2025-07-02 06:41:16.738                 elif tag == 'delete':
2025-07-02 06:41:16.738                     atags += '-' * la
2025-07-02 06:41:16.738                 elif tag == 'insert':
2025-07-02 06:41:16.738                     btags += '+' * lb
2025-07-02 06:41:16.738                 elif tag == 'equal':
2025-07-02 06:41:16.738                     atags += ' ' * la
2025-07-02 06:41:16.738                     btags += ' ' * lb
2025-07-02 06:41:16.738                 else:
2025-07-02 06:41:16.738                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.738             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.738         else:
2025-07-02 06:41:16.739             # the synch pair is identical
2025-07-02 06:41:16.739             yield '  ' + aelt
2025-07-02 06:41:16.739
2025-07-02 06:41:16.739         # pump out diffs from after the synch point
2025-07-02 06:41:16.739 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.739
2025-07-02 06:41:16.739 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.739 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.739
2025-07-02 06:41:16.739 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.739 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.739 alo = 108, ahi = 1101
2025-07-02 06:41:16.739 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.739 blo = 108, bhi = 1101
2025-07-02 06:41:16.739
2025-07-02 06:41:16.739     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.739         g = []
2025-07-02 06:41:16.739         if alo < ahi:
2025-07-02 06:41:16.739             if blo < bhi:
2025-07-02 06:41:16.740                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.740             else:
2025-07-02 06:41:16.740                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.740         elif blo < bhi:
2025-07-02 06:41:16.740             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.740
2025-07-02 06:41:16.740 >       yield from g
2025-07-02 06:41:16.740
2025-07-02 06:41:16.740 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.740 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.740
2025-07-02 06:41:16.740 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.740 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.740 alo = 108, ahi = 1101
2025-07-02 06:41:16.740 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.740 blo = 108, bhi = 1101
2025-07-02 06:41:16.740
2025-07-02 06:41:16.740     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.740         r"""
2025-07-02 06:41:16.741         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.741         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.741         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.741         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.741
2025-07-02 06:41:16.741         Example:
2025-07-02 06:41:16.741
2025-07-02 06:41:16.741         >>> d = Differ()
2025-07-02 06:41:16.741         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.741         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.741         >>> print(''.join(results), end="")
2025-07-02 06:41:16.741         - abcDefghiJkl
2025-07-02 06:41:16.741         + abcdefGhijkl
2025-07-02 06:41:16.741         """
2025-07-02 06:41:16.741
2025-07-02 06:41:16.741         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.741         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.741         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.741         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.742         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.742
2025-07-02 06:41:16.742         # search for the pair that matches best without being identical
2025-07-02 06:41:16.742         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.742         # on junk -- unless we have to)
2025-07-02 06:41:16.742         for j in range(blo, bhi):
2025-07-02 06:41:16.742             bj = b[j]
2025-07-02 06:41:16.742             cruncher.set_seq2(bj)
2025-07-02 06:41:16.742             for i in range(alo, ahi):
2025-07-02 06:41:16.742                 ai = a[i]
2025-07-02 06:41:16.742                 if ai == bj:
2025-07-02 06:41:16.742                     if eqi is None:
2025-07-02 06:41:16.742                         eqi, eqj = i, j
2025-07-02 06:41:16.742                     continue
2025-07-02 06:41:16.742                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.742                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.742                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.742                 # compares by a factor of 3.
2025-07-02 06:41:16.742                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.742                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.743                 # of the computation is cached by cruncher
2025-07-02 06:41:16.743                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.743                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.743                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.743                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.743         if best_ratio < cutoff:
2025-07-02 06:41:16.743             # no non-identical "pretty close" pair
2025-07-02 06:41:16.743             if eqi is None:
2025-07-02 06:41:16.743                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.743                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.743                 return
2025-07-02 06:41:16.743             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.743             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.743         else:
2025-07-02 06:41:16.743             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.743             eqi = None
2025-07-02 06:41:16.743
2025-07-02 06:41:16.743         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.743         # identical
2025-07-02 06:41:16.743
2025-07-02 06:41:16.744         # pump out diffs from before the synch point
2025-07-02 06:41:16.744         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.744
2025-07-02 06:41:16.744         # do intraline marking on the synch pair
2025-07-02 06:41:16.744         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.744         if eqi is None:
2025-07-02 06:41:16.744             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.744             atags = btags = ""
2025-07-02 06:41:16.744             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.744             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.744                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.744                 if tag == 'replace':
2025-07-02 06:41:16.744                     atags += '^' * la
2025-07-02 06:41:16.744                     btags += '^' * lb
2025-07-02 06:41:16.744                 elif tag == 'delete':
2025-07-02 06:41:16.744                     atags += '-' * la
2025-07-02 06:41:16.744                 elif tag == 'insert':
2025-07-02 06:41:16.744                     btags += '+' * lb
2025-07-02 06:41:16.744                 elif tag == 'equal':
2025-07-02 06:41:16.744                     atags += ' ' * la
2025-07-02 06:41:16.745                     btags += ' ' * lb
2025-07-02 06:41:16.745                 else:
2025-07-02 06:41:16.745                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.745             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.745         else:
2025-07-02 06:41:16.745             # the synch pair is identical
2025-07-02 06:41:16.745             yield '  ' + aelt
2025-07-02 06:41:16.745
2025-07-02 06:41:16.745         # pump out diffs from after the synch point
2025-07-02 06:41:16.745 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.745
2025-07-02 06:41:16.745 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.745 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.745
2025-07-02 06:41:16.745 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.745 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.745 alo = 109, ahi = 1101
2025-07-02 06:41:16.746 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.746 blo = 109, bhi = 1101
2025-07-02 06:41:16.746
2025-07-02 06:41:16.746     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.746         g = []
2025-07-02 06:41:16.746         if alo < ahi:
2025-07-02 06:41:16.746             if blo < bhi:
2025-07-02 06:41:16.746                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.746             else:
2025-07-02 06:41:16.746                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.746         elif blo < bhi:
2025-07-02 06:41:16.746             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.746
2025-07-02 06:41:16.746 >       yield from g
2025-07-02 06:41:16.746
2025-07-02 06:41:16.746 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.746 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.746
2025-07-02 06:41:16.746 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.747 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.747 alo = 109, ahi = 1101
2025-07-02 06:41:16.747 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.747 blo = 109, bhi = 1101
2025-07-02 06:41:16.747
2025-07-02 06:41:16.747     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.747         r"""
2025-07-02 06:41:16.747         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.747         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.747         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.747         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.747
2025-07-02 06:41:16.747         Example:
2025-07-02 06:41:16.747
2025-07-02 06:41:16.747         >>> d = Differ()
2025-07-02 06:41:16.747         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.747         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.747         >>> print(''.join(results), end="")
2025-07-02 06:41:16.747         - abcDefghiJkl
2025-07-02 06:41:16.748         + abcdefGhijkl
2025-07-02 06:41:16.748         """
2025-07-02 06:41:16.748
2025-07-02 06:41:16.748         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.748         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.748         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.748         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.748         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.748
2025-07-02 06:41:16.748         # search for the pair that matches best without being identical
2025-07-02 06:41:16.748         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.748         # on junk -- unless we have to)
2025-07-02 06:41:16.748         for j in range(blo, bhi):
2025-07-02 06:41:16.748             bj = b[j]
2025-07-02 06:41:16.748             cruncher.set_seq2(bj)
2025-07-02 06:41:16.748             for i in range(alo, ahi):
2025-07-02 06:41:16.748                 ai = a[i]
2025-07-02 06:41:16.748                 if ai == bj:
2025-07-02 06:41:16.748                     if eqi is None:
2025-07-02 06:41:16.749                         eqi, eqj = i, j
2025-07-02 06:41:16.749                     continue
2025-07-02 06:41:16.749                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.749                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.749                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.749                 # compares by a factor of 3.
2025-07-02 06:41:16.749                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.749                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.749                 # of the computation is cached by cruncher
2025-07-02 06:41:16.749                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.749                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.749                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.749                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.749         if best_ratio < cutoff:
2025-07-02 06:41:16.749             # no non-identical "pretty close" pair
2025-07-02 06:41:16.749             if eqi is None:
2025-07-02 06:41:16.749                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.749                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.749                 return
2025-07-02 06:41:16.749             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.749             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.750         else:
2025-07-02 06:41:16.750             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.750             eqi = None
2025-07-02 06:41:16.750
2025-07-02 06:41:16.750         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.750         # identical
2025-07-02 06:41:16.750
2025-07-02 06:41:16.750         # pump out diffs from before the synch point
2025-07-02 06:41:16.750         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.750
2025-07-02 06:41:16.750         # do intraline marking on the synch pair
2025-07-02 06:41:16.750         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.750         if eqi is None:
2025-07-02 06:41:16.750             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.750             atags = btags = ""
2025-07-02 06:41:16.750             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.750             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.750                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.750                 if tag == 'replace':
2025-07-02 06:41:16.750                     atags += '^' * la
2025-07-02 06:41:16.751                     btags += '^' * lb
2025-07-02 06:41:16.751                 elif tag == 'delete':
2025-07-02 06:41:16.751                     atags += '-' * la
2025-07-02 06:41:16.751                 elif tag == 'insert':
2025-07-02 06:41:16.751                     btags += '+' * lb
2025-07-02 06:41:16.751                 elif tag == 'equal':
2025-07-02 06:41:16.751                     atags += ' ' * la
2025-07-02 06:41:16.751                     btags += ' ' * lb
2025-07-02 06:41:16.751                 else:
2025-07-02 06:41:16.751                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.751             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.751         else:
2025-07-02 06:41:16.751             # the synch pair is identical
2025-07-02 06:41:16.751             yield '  ' + aelt
2025-07-02 06:41:16.751
2025-07-02 06:41:16.751         # pump out diffs from after the synch point
2025-07-02 06:41:16.751 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.751
2025-07-02 06:41:16.751 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.751 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.752
2025-07-02 06:41:16.752 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.752 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.752 alo = 110, ahi = 1101
2025-07-02 06:41:16.752 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.752 blo = 110, bhi = 1101
2025-07-02 06:41:16.752
2025-07-02 06:41:16.752     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.752         g = []
2025-07-02 06:41:16.752         if alo < ahi:
2025-07-02 06:41:16.752             if blo < bhi:
2025-07-02 06:41:16.752                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.752             else:
2025-07-02 06:41:16.752                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.752         elif blo < bhi:
2025-07-02 06:41:16.752             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.752
2025-07-02 06:41:16.752 >       yield from g
2025-07-02 06:41:16.752
2025-07-02 06:41:16.752 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.752 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.753
2025-07-02 06:41:16.753 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.753 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.753 alo = 110, ahi = 1101
2025-07-02 06:41:16.753 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.753 blo = 110, bhi = 1101
2025-07-02 06:41:16.753
2025-07-02 06:41:16.753     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.753         r"""
2025-07-02 06:41:16.753         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.753         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.753         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.753         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.753
2025-07-02 06:41:16.753         Example:
2025-07-02 06:41:16.753
2025-07-02 06:41:16.753         >>> d = Differ()
2025-07-02 06:41:16.753         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.753         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.754         >>> print(''.join(results), end="")
2025-07-02 06:41:16.754         - abcDefghiJkl
2025-07-02 06:41:16.754         + abcdefGhijkl
2025-07-02 06:41:16.754         """
2025-07-02 06:41:16.754
2025-07-02 06:41:16.754         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.754         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.754         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.754         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.754         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.754
2025-07-02 06:41:16.754         # search for the pair that matches best without being identical
2025-07-02 06:41:16.754         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.754         # on junk -- unless we have to)
2025-07-02 06:41:16.754         for j in range(blo, bhi):
2025-07-02 06:41:16.754             bj = b[j]
2025-07-02 06:41:16.754             cruncher.set_seq2(bj)
2025-07-02 06:41:16.755             for i in range(alo, ahi):
2025-07-02 06:41:16.755                 ai = a[i]
2025-07-02 06:41:16.755                 if ai == bj:
2025-07-02 06:41:16.755                     if eqi is None:
2025-07-02 06:41:16.755                         eqi, eqj = i, j
2025-07-02 06:41:16.755                     continue
2025-07-02 06:41:16.755                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.755                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.755                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.755                 # compares by a factor of 3.
2025-07-02 06:41:16.755                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.755                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.755                 # of the computation is cached by cruncher
2025-07-02 06:41:16.755                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.755                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.755                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.755                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.755         if best_ratio < cutoff:
2025-07-02 06:41:16.755             # no non-identical "pretty close" pair
2025-07-02 06:41:16.755             if eqi is None:
2025-07-02 06:41:16.756                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.756                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.756                 return
2025-07-02 06:41:16.756             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.756             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.756         else:
2025-07-02 06:41:16.756             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.756             eqi = None
2025-07-02 06:41:16.756
2025-07-02 06:41:16.756         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.756         # identical
2025-07-02 06:41:16.756
2025-07-02 06:41:16.756         # pump out diffs from before the synch point
2025-07-02 06:41:16.756         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.756
2025-07-02 06:41:16.756         # do intraline marking on the synch pair
2025-07-02 06:41:16.756         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.756         if eqi is None:
2025-07-02 06:41:16.756             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.756             atags = btags = ""
2025-07-02 06:41:16.757             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.757             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.757                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.757                 if tag == 'replace':
2025-07-02 06:41:16.757                     atags += '^' * la
2025-07-02 06:41:16.757                     btags += '^' * lb
2025-07-02 06:41:16.757                 elif tag == 'delete':
2025-07-02 06:41:16.757                     atags += '-' * la
2025-07-02 06:41:16.757                 elif tag == 'insert':
2025-07-02 06:41:16.757                     btags += '+' * lb
2025-07-02 06:41:16.757                 elif tag == 'equal':
2025-07-02 06:41:16.757                     atags += ' ' * la
2025-07-02 06:41:16.757                     btags += ' ' * lb
2025-07-02 06:41:16.757                 else:
2025-07-02 06:41:16.757                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.757             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.757         else:
2025-07-02 06:41:16.757             # the synch pair is identical
2025-07-02 06:41:16.757             yield '  ' + aelt
2025-07-02 06:41:16.757
2025-07-02 06:41:16.758         # pump out diffs from after the synch point
2025-07-02 06:41:16.758 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.758
2025-07-02 06:41:16.758 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.758 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.758
2025-07-02 06:41:16.758 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.758 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.758 alo = 111, ahi = 1101
2025-07-02 06:41:16.758 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.758 blo = 111, bhi = 1101
2025-07-02 06:41:16.758
2025-07-02 06:41:16.758     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.758         g = []
2025-07-02 06:41:16.758         if alo < ahi:
2025-07-02 06:41:16.758             if blo < bhi:
2025-07-02 06:41:16.758                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.758             else:
2025-07-02 06:41:16.758                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.758         elif blo < bhi:
2025-07-02 06:41:16.759             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.759
2025-07-02 06:41:16.759 >       yield from g
2025-07-02 06:41:16.759
2025-07-02 06:41:16.759 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.759 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.759
2025-07-02 06:41:16.759 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.759 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.759 alo = 111, ahi = 1101
2025-07-02 06:41:16.759 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.759 blo = 111, bhi = 1101
2025-07-02 06:41:16.759
2025-07-02 06:41:16.759     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.759         r"""
2025-07-02 06:41:16.759         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.759         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.759         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.759         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.759
2025-07-02 06:41:16.760         Example:
2025-07-02 06:41:16.760
2025-07-02 06:41:16.760         >>> d = Differ()
2025-07-02 06:41:16.760         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.760         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.760         >>> print(''.join(results), end="")
2025-07-02 06:41:16.760         - abcDefghiJkl
2025-07-02 06:41:16.760         + abcdefGhijkl
2025-07-02 06:41:16.760         """
2025-07-02 06:41:16.760
2025-07-02 06:41:16.760         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.760         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.760         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.760         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.760         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.760
2025-07-02 06:41:16.760         # search for the pair that matches best without being identical
2025-07-02 06:41:16.760         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.761         # on junk -- unless we have to)
2025-07-02 06:41:16.761         for j in range(blo, bhi):
2025-07-02 06:41:16.761             bj = b[j]
2025-07-02 06:41:16.761             cruncher.set_seq2(bj)
2025-07-02 06:41:16.761             for i in range(alo, ahi):
2025-07-02 06:41:16.761                 ai = a[i]
2025-07-02 06:41:16.761                 if ai == bj:
2025-07-02 06:41:16.761                     if eqi is None:
2025-07-02 06:41:16.761                         eqi, eqj = i, j
2025-07-02 06:41:16.761                     continue
2025-07-02 06:41:16.761                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.761                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.761                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.761                 # compares by a factor of 3.
2025-07-02 06:41:16.761                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.761                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.761                 # of the computation is cached by cruncher
2025-07-02 06:41:16.761                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.761                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.762                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.762                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.762         if best_ratio < cutoff:
2025-07-02 06:41:16.762             # no non-identical "pretty close" pair
2025-07-02 06:41:16.762             if eqi is None:
2025-07-02 06:41:16.762                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.762                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.762                 return
2025-07-02 06:41:16.762             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.762             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.762         else:
2025-07-02 06:41:16.762             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.762             eqi = None
2025-07-02 06:41:16.762
2025-07-02 06:41:16.762         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.762         # identical
2025-07-02 06:41:16.762
2025-07-02 06:41:16.762         # pump out diffs from before the synch point
2025-07-02 06:41:16.763         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.763
2025-07-02 06:41:16.763         # do intraline marking on the synch pair
2025-07-02 06:41:16.763         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.763         if eqi is None:
2025-07-02 06:41:16.763             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.763             atags = btags = ""
2025-07-02 06:41:16.763             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.763             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.763                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.763                 if tag == 'replace':
2025-07-02 06:41:16.763                     atags += '^' * la
2025-07-02 06:41:16.763                     btags += '^' * lb
2025-07-02 06:41:16.763                 elif tag == 'delete':
2025-07-02 06:41:16.763                     atags += '-' * la
2025-07-02 06:41:16.763                 elif tag == 'insert':
2025-07-02 06:41:16.763                     btags += '+' * lb
2025-07-02 06:41:16.763                 elif tag == 'equal':
2025-07-02 06:41:16.764                     atags += ' ' * la
2025-07-02 06:41:16.764                     btags += ' ' * lb
2025-07-02 06:41:16.764                 else:
2025-07-02 06:41:16.764                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.764             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.764         else:
2025-07-02 06:41:16.764             # the synch pair is identical
2025-07-02 06:41:16.764             yield '  ' + aelt
2025-07-02 06:41:16.764
2025-07-02 06:41:16.764         # pump out diffs from after the synch point
2025-07-02 06:41:16.764 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.764
2025-07-02 06:41:16.764 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.764 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.764
2025-07-02 06:41:16.764 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.764 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.764 alo = 114, ahi = 1101
2025-07-02 06:41:16.764 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.765 blo = 114, bhi = 1101
2025-07-02 06:41:16.765
2025-07-02 06:41:16.765     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.765         g = []
2025-07-02 06:41:16.765         if alo < ahi:
2025-07-02 06:41:16.765             if blo < bhi:
2025-07-02 06:41:16.765                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.765             else:
2025-07-02 06:41:16.765                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.765         elif blo < bhi:
2025-07-02 06:41:16.765             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.765
2025-07-02 06:41:16.765 >       yield from g
2025-07-02 06:41:16.765
2025-07-02 06:41:16.765 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.765 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.765
2025-07-02 06:41:16.765 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.765 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.765 alo = 114, ahi = 1101
2025-07-02 06:41:16.766 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.766 blo = 114, bhi = 1101
2025-07-02 06:41:16.766
2025-07-02 06:41:16.766     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.766         r"""
2025-07-02 06:41:16.766         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.766         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.766         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.766         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.766
2025-07-02 06:41:16.766         Example:
2025-07-02 06:41:16.766
2025-07-02 06:41:16.766         >>> d = Differ()
2025-07-02 06:41:16.766         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.766         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.766         >>> print(''.join(results), end="")
2025-07-02 06:41:16.766         - abcDefghiJkl
2025-07-02 06:41:16.766         + abcdefGhijkl
2025-07-02 06:41:16.767         """
2025-07-02 06:41:16.767
2025-07-02 06:41:16.767         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.767         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.767         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.767         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.767         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.767
2025-07-02 06:41:16.767         # search for the pair that matches best without being identical
2025-07-02 06:41:16.767         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.767         # on junk -- unless we have to)
2025-07-02 06:41:16.767         for j in range(blo, bhi):
2025-07-02 06:41:16.767             bj = b[j]
2025-07-02 06:41:16.767             cruncher.set_seq2(bj)
2025-07-02 06:41:16.767             for i in range(alo, ahi):
2025-07-02 06:41:16.767                 ai = a[i]
2025-07-02 06:41:16.767                 if ai == bj:
2025-07-02 06:41:16.767                     if eqi is None:
2025-07-02 06:41:16.767                         eqi, eqj = i, j
2025-07-02 06:41:16.768                     continue
2025-07-02 06:41:16.768                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.768                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.768                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.768                 # compares by a factor of 3.
2025-07-02 06:41:16.768                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.768                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.768                 # of the computation is cached by cruncher
2025-07-02 06:41:16.768                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.768                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.768                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.768                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.768         if best_ratio < cutoff:
2025-07-02 06:41:16.768             # no non-identical "pretty close" pair
2025-07-02 06:41:16.768             if eqi is None:
2025-07-02 06:41:16.768                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.768                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.768                 return
2025-07-02 06:41:16.768             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.769             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.769         else:
2025-07-02 06:41:16.769             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.769             eqi = None
2025-07-02 06:41:16.769
2025-07-02 06:41:16.769         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.769         # identical
2025-07-02 06:41:16.769
2025-07-02 06:41:16.769         # pump out diffs from before the synch point
2025-07-02 06:41:16.769         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.769
2025-07-02 06:41:16.769         # do intraline marking on the synch pair
2025-07-02 06:41:16.769         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.769         if eqi is None:
2025-07-02 06:41:16.769             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.769             atags = btags = ""
2025-07-02 06:41:16.769             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.769             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.769                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.770                 if tag == 'replace':
2025-07-02 06:41:16.770                     atags += '^' * la
2025-07-02 06:41:16.770                     btags += '^' * lb
2025-07-02 06:41:16.770                 elif tag == 'delete':
2025-07-02 06:41:16.770                     atags += '-' * la
2025-07-02 06:41:16.770                 elif tag == 'insert':
2025-07-02 06:41:16.770                     btags += '+' * lb
2025-07-02 06:41:16.770                 elif tag == 'equal':
2025-07-02 06:41:16.770                     atags += ' ' * la
2025-07-02 06:41:16.770                     btags += ' ' * lb
2025-07-02 06:41:16.770                 else:
2025-07-02 06:41:16.770                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.770             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.770         else:
2025-07-02 06:41:16.770             # the synch pair is identical
2025-07-02 06:41:16.770             yield '  ' + aelt
2025-07-02 06:41:16.770
2025-07-02 06:41:16.770         # pump out diffs from after the synch point
2025-07-02 06:41:16.770 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.770
2025-07-02 06:41:16.771 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.771 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.771
2025-07-02 06:41:16.771 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.771 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.771 alo = 115, ahi = 1101
2025-07-02 06:41:16.771 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.771 blo = 115, bhi = 1101
2025-07-02 06:41:16.771
2025-07-02 06:41:16.771     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.771         g = []
2025-07-02 06:41:16.771         if alo < ahi:
2025-07-02 06:41:16.771             if blo < bhi:
2025-07-02 06:41:16.771                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.771             else:
2025-07-02 06:41:16.771                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.771         elif blo < bhi:
2025-07-02 06:41:16.771             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772 >       yield from g
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.772 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.772 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.772 alo = 115, ahi = 1101
2025-07-02 06:41:16.772 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.772 blo = 115, bhi = 1101
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.772         r"""
2025-07-02 06:41:16.772         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.772         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.772         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.772         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.772
2025-07-02 06:41:16.772         Example:
2025-07-02 06:41:16.773
2025-07-02 06:41:16.773         >>> d = Differ()
2025-07-02 06:41:16.773         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.773         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.773         >>> print(''.join(results), end="")
2025-07-02 06:41:16.773         - abcDefghiJkl
2025-07-02 06:41:16.773         + abcdefGhijkl
2025-07-02 06:41:16.773         """
2025-07-02 06:41:16.773
2025-07-02 06:41:16.773         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.773         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.773         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.773         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.773         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.773
2025-07-02 06:41:16.773         # search for the pair that matches best without being identical
2025-07-02 06:41:16.773         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.773         # on junk -- unless we have to)
2025-07-02 06:41:16.774         for j in range(blo, bhi):
2025-07-02 06:41:16.774             bj = b[j]
2025-07-02 06:41:16.774             cruncher.set_seq2(bj)
2025-07-02 06:41:16.774             for i in range(alo, ahi):
2025-07-02 06:41:16.774                 ai = a[i]
2025-07-02 06:41:16.774                 if ai == bj:
2025-07-02 06:41:16.774                     if eqi is None:
2025-07-02 06:41:16.774                         eqi, eqj = i, j
2025-07-02 06:41:16.774                     continue
2025-07-02 06:41:16.774                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.774                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.774                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.774                 # compares by a factor of 3.
2025-07-02 06:41:16.774                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.774                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.774                 # of the computation is cached by cruncher
2025-07-02 06:41:16.774                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.774                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.774                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.774                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.775         if best_ratio < cutoff:
2025-07-02 06:41:16.775             # no non-identical "pretty close" pair
2025-07-02 06:41:16.775             if eqi is None:
2025-07-02 06:41:16.775                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.775                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.775                 return
2025-07-02 06:41:16.775             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.775             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.775         else:
2025-07-02 06:41:16.775             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.775             eqi = None
2025-07-02 06:41:16.775
2025-07-02 06:41:16.775         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.775         # identical
2025-07-02 06:41:16.775
2025-07-02 06:41:16.775         # pump out diffs from before the synch point
2025-07-02 06:41:16.775         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.775
2025-07-02 06:41:16.775         # do intraline marking on the synch pair
2025-07-02 06:41:16.775         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.775         if eqi is None:
2025-07-02 06:41:16.776             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.776             atags = btags = ""
2025-07-02 06:41:16.776             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.776             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.776                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.776                 if tag == 'replace':
2025-07-02 06:41:16.776                     atags += '^' * la
2025-07-02 06:41:16.776                     btags += '^' * lb
2025-07-02 06:41:16.776                 elif tag == 'delete':
2025-07-02 06:41:16.776                     atags += '-' * la
2025-07-02 06:41:16.776                 elif tag == 'insert':
2025-07-02 06:41:16.776                     btags += '+' * lb
2025-07-02 06:41:16.776                 elif tag == 'equal':
2025-07-02 06:41:16.776                     atags += ' ' * la
2025-07-02 06:41:16.776                     btags += ' ' * lb
2025-07-02 06:41:16.776                 else:
2025-07-02 06:41:16.776                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.776             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.776         else:
2025-07-02 06:41:16.776             # the synch pair is identical
2025-07-02 06:41:16.777             yield '  ' + aelt
2025-07-02 06:41:16.777
2025-07-02 06:41:16.777         # pump out diffs from after the synch point
2025-07-02 06:41:16.777 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.777
2025-07-02 06:41:16.777 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.777 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.777
2025-07-02 06:41:16.777 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.777 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.777 alo = 116, ahi = 1101
2025-07-02 06:41:16.777 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.777 blo = 116, bhi = 1101
2025-07-02 06:41:16.777
2025-07-02 06:41:16.777     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.777         g = []
2025-07-02 06:41:16.777         if alo < ahi:
2025-07-02 06:41:16.777             if blo < bhi:
2025-07-02 06:41:16.778                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.778             else:
2025-07-02 06:41:16.778                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.778         elif blo < bhi:
2025-07-02 06:41:16.778             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.778
2025-07-02 06:41:16.778 >       yield from g
2025-07-02 06:41:16.778
2025-07-02 06:41:16.778 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.778 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.778
2025-07-02 06:41:16.778 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.778 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.778 alo = 116, ahi = 1101
2025-07-02 06:41:16.778 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.778 blo = 116, bhi = 1101
2025-07-02 06:41:16.778
2025-07-02 06:41:16.778     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.778         r"""
2025-07-02 06:41:16.778         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.779         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.779         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.779         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.779
2025-07-02 06:41:16.779         Example:
2025-07-02 06:41:16.779
2025-07-02 06:41:16.779         >>> d = Differ()
2025-07-02 06:41:16.779         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.779         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.779         >>> print(''.join(results), end="")
2025-07-02 06:41:16.779         - abcDefghiJkl
2025-07-02 06:41:16.779         + abcdefGhijkl
2025-07-02 06:41:16.779         """
2025-07-02 06:41:16.779
2025-07-02 06:41:16.779         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.779         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.779         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.779         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.780         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.780
2025-07-02 06:41:16.780         # search for the pair that matches best without being identical
2025-07-02 06:41:16.780         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.780         # on junk -- unless we have to)
2025-07-02 06:41:16.780         for j in range(blo, bhi):
2025-07-02 06:41:16.780             bj = b[j]
2025-07-02 06:41:16.780             cruncher.set_seq2(bj)
2025-07-02 06:41:16.780             for i in range(alo, ahi):
2025-07-02 06:41:16.780                 ai = a[i]
2025-07-02 06:41:16.780                 if ai == bj:
2025-07-02 06:41:16.780                     if eqi is None:
2025-07-02 06:41:16.780                         eqi, eqj = i, j
2025-07-02 06:41:16.780                     continue
2025-07-02 06:41:16.780                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.780                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.780                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.780                 # compares by a factor of 3.
2025-07-02 06:41:16.780                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.781                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.781                 # of the computation is cached by cruncher
2025-07-02 06:41:16.781                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.781                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.781                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.781                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.781         if best_ratio < cutoff:
2025-07-02 06:41:16.781             # no non-identical "pretty close" pair
2025-07-02 06:41:16.781             if eqi is None:
2025-07-02 06:41:16.781                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.781                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.781                 return
2025-07-02 06:41:16.781             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.781             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.781         else:
2025-07-02 06:41:16.781             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.781             eqi = None
2025-07-02 06:41:16.781
2025-07-02 06:41:16.781         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.782         # identical
2025-07-02 06:41:16.782
2025-07-02 06:41:16.782         # pump out diffs from before the synch point
2025-07-02 06:41:16.782         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.782
2025-07-02 06:41:16.782         # do intraline marking on the synch pair
2025-07-02 06:41:16.782         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.782         if eqi is None:
2025-07-02 06:41:16.782             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.782             atags = btags = ""
2025-07-02 06:41:16.782             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.782             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.782                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.782                 if tag == 'replace':
2025-07-02 06:41:16.782                     atags += '^' * la
2025-07-02 06:41:16.782                     btags += '^' * lb
2025-07-02 06:41:16.782                 elif tag == 'delete':
2025-07-02 06:41:16.782                     atags += '-' * la
2025-07-02 06:41:16.782                 elif tag == 'insert':
2025-07-02 06:41:16.782                     btags += '+' * lb
2025-07-02 06:41:16.783                 elif tag == 'equal':
2025-07-02 06:41:16.783                     atags += ' ' * la
2025-07-02 06:41:16.783                     btags += ' ' * lb
2025-07-02 06:41:16.783                 else:
2025-07-02 06:41:16.783                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.783             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.783         else:
2025-07-02 06:41:16.783             # the synch pair is identical
2025-07-02 06:41:16.783             yield '  ' + aelt
2025-07-02 06:41:16.783
2025-07-02 06:41:16.783         # pump out diffs from after the synch point
2025-07-02 06:41:16.783 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.783
2025-07-02 06:41:16.783 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.783 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.783
2025-07-02 06:41:16.783 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.783 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.783 alo = 117, ahi = 1101
2025-07-02 06:41:16.783 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.784 blo = 117, bhi = 1101
2025-07-02 06:41:16.784
2025-07-02 06:41:16.784     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.784         g = []
2025-07-02 06:41:16.784         if alo < ahi:
2025-07-02 06:41:16.784             if blo < bhi:
2025-07-02 06:41:16.784                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.784             else:
2025-07-02 06:41:16.784                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.784         elif blo < bhi:
2025-07-02 06:41:16.784             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.784
2025-07-02 06:41:16.784 >       yield from g
2025-07-02 06:41:16.784
2025-07-02 06:41:16.784 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.784 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.784
2025-07-02 06:41:16.784 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.784 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.784 alo = 117, ahi = 1101
2025-07-02 06:41:16.785 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.785 blo = 117, bhi = 1101
2025-07-02 06:41:16.785
2025-07-02 06:41:16.785     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.785         r"""
2025-07-02 06:41:16.785         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.785         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.785         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.785         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.785
2025-07-02 06:41:16.785         Example:
2025-07-02 06:41:16.785
2025-07-02 06:41:16.785         >>> d = Differ()
2025-07-02 06:41:16.785         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.785         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.785         >>> print(''.join(results), end="")
2025-07-02 06:41:16.785         - abcDefghiJkl
2025-07-02 06:41:16.785         + abcdefGhijkl
2025-07-02 06:41:16.786         """
2025-07-02 06:41:16.786
2025-07-02 06:41:16.786         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.786         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.786         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.786         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.786         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.786
2025-07-02 06:41:16.786         # search for the pair that matches best without being identical
2025-07-02 06:41:16.786         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.786         # on junk -- unless we have to)
2025-07-02 06:41:16.786         for j in range(blo, bhi):
2025-07-02 06:41:16.786             bj = b[j]
2025-07-02 06:41:16.786             cruncher.set_seq2(bj)
2025-07-02 06:41:16.786             for i in range(alo, ahi):
2025-07-02 06:41:16.786                 ai = a[i]
2025-07-02 06:41:16.786                 if ai == bj:
2025-07-02 06:41:16.786                     if eqi is None:
2025-07-02 06:41:16.786                         eqi, eqj = i, j
2025-07-02 06:41:16.786                     continue
2025-07-02 06:41:16.786                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.787                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.787                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.787                 # compares by a factor of 3.
2025-07-02 06:41:16.787                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.787                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.787                 # of the computation is cached by cruncher
2025-07-02 06:41:16.787                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.787                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.787                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.787                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.787         if best_ratio < cutoff:
2025-07-02 06:41:16.787             # no non-identical "pretty close" pair
2025-07-02 06:41:16.787             if eqi is None:
2025-07-02 06:41:16.787                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.787                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.787                 return
2025-07-02 06:41:16.787             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.787             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.787         else:
2025-07-02 06:41:16.787             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.788             eqi = None
2025-07-02 06:41:16.788
2025-07-02 06:41:16.788         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.788         # identical
2025-07-02 06:41:16.788
2025-07-02 06:41:16.788         # pump out diffs from before the synch point
2025-07-02 06:41:16.788         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.788
2025-07-02 06:41:16.788         # do intraline marking on the synch pair
2025-07-02 06:41:16.788         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.788         if eqi is None:
2025-07-02 06:41:16.788             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.788             atags = btags = ""
2025-07-02 06:41:16.788             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.788             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.788                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.788                 if tag == 'replace':
2025-07-02 06:41:16.788                     atags += '^' * la
2025-07-02 06:41:16.788                     btags += '^' * lb
2025-07-02 06:41:16.788                 elif tag == 'delete':
2025-07-02 06:41:16.789                     atags += '-' * la
2025-07-02 06:41:16.789                 elif tag == 'insert':
2025-07-02 06:41:16.789                     btags += '+' * lb
2025-07-02 06:41:16.789                 elif tag == 'equal':
2025-07-02 06:41:16.789                     atags += ' ' * la
2025-07-02 06:41:16.789                     btags += ' ' * lb
2025-07-02 06:41:16.789                 else:
2025-07-02 06:41:16.789                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.789             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.789         else:
2025-07-02 06:41:16.789             # the synch pair is identical
2025-07-02 06:41:16.789             yield '  ' + aelt
2025-07-02 06:41:16.789
2025-07-02 06:41:16.789         # pump out diffs from after the synch point
2025-07-02 06:41:16.789 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.789
2025-07-02 06:41:16.789 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.789 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.790
2025-07-02 06:41:16.790 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.790 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.790 alo = 118, ahi = 1101
2025-07-02 06:41:16.790 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.790 blo = 118, bhi = 1101
2025-07-02 06:41:16.790
2025-07-02 06:41:16.790     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.790         g = []
2025-07-02 06:41:16.790         if alo < ahi:
2025-07-02 06:41:16.790             if blo < bhi:
2025-07-02 06:41:16.790                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.790             else:
2025-07-02 06:41:16.790                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.790         elif blo < bhi:
2025-07-02 06:41:16.790             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.790
2025-07-02 06:41:16.790 >       yield from g
2025-07-02 06:41:16.790
2025-07-02 06:41:16.791 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.791 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.791
2025-07-02 06:41:16.791 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.791 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.791 alo = 118, ahi = 1101
2025-07-02 06:41:16.791 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.791 blo = 118, bhi = 1101
2025-07-02 06:41:16.791
2025-07-02 06:41:16.791     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.791         r"""
2025-07-02 06:41:16.791         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.791         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.791         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.791         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.791
2025-07-02 06:41:16.791         Example:
2025-07-02 06:41:16.791
2025-07-02 06:41:16.791         >>> d = Differ()
2025-07-02 06:41:16.791         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.792         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.792         >>> print(''.join(results), end="")
2025-07-02 06:41:16.792         - abcDefghiJkl
2025-07-02 06:41:16.792         + abcdefGhijkl
2025-07-02 06:41:16.792         """
2025-07-02 06:41:16.792
2025-07-02 06:41:16.792         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.792         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.792         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.792         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.792         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.792
2025-07-02 06:41:16.792         # search for the pair that matches best without being identical
2025-07-02 06:41:16.792         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.792         # on junk -- unless we have to)
2025-07-02 06:41:16.792         for j in range(blo, bhi):
2025-07-02 06:41:16.792             bj = b[j]
2025-07-02 06:41:16.792             cruncher.set_seq2(bj)
2025-07-02 06:41:16.792             for i in range(alo, ahi):
2025-07-02 06:41:16.793                 ai = a[i]
2025-07-02 06:41:16.793                 if ai == bj:
2025-07-02 06:41:16.793                     if eqi is None:
2025-07-02 06:41:16.793                         eqi, eqj = i, j
2025-07-02 06:41:16.793                     continue
2025-07-02 06:41:16.793                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.793                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.793                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.793                 # compares by a factor of 3.
2025-07-02 06:41:16.793                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.793                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.793                 # of the computation is cached by cruncher
2025-07-02 06:41:16.793                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.793                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.793                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.793                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.793         if best_ratio < cutoff:
2025-07-02 06:41:16.794             # no non-identical "pretty close" pair
2025-07-02 06:41:16.794             if eqi is None:
2025-07-02 06:41:16.794                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.794                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.794                 return
2025-07-02 06:41:16.794             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.794             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.794         else:
2025-07-02 06:41:16.794             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.794             eqi = None
2025-07-02 06:41:16.794
2025-07-02 06:41:16.794         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.794         # identical
2025-07-02 06:41:16.794
2025-07-02 06:41:16.794         # pump out diffs from before the synch point
2025-07-02 06:41:16.794         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.794
2025-07-02 06:41:16.794         # do intraline marking on the synch pair
2025-07-02 06:41:16.794         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.794         if eqi is None:
2025-07-02 06:41:16.795             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.795             atags = btags = ""
2025-07-02 06:41:16.795             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.795             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.795                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.795                 if tag == 'replace':
2025-07-02 06:41:16.795                     atags += '^' * la
2025-07-02 06:41:16.795                     btags += '^' * lb
2025-07-02 06:41:16.795                 elif tag == 'delete':
2025-07-02 06:41:16.795                     atags += '-' * la
2025-07-02 06:41:16.795                 elif tag == 'insert':
2025-07-02 06:41:16.795                     btags += '+' * lb
2025-07-02 06:41:16.795                 elif tag == 'equal':
2025-07-02 06:41:16.795                     atags += ' ' * la
2025-07-02 06:41:16.795                     btags += ' ' * lb
2025-07-02 06:41:16.795                 else:
2025-07-02 06:41:16.795                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.795             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.795         else:
2025-07-02 06:41:16.795             # the synch pair is identical
2025-07-02 06:41:16.796             yield '  ' + aelt
2025-07-02 06:41:16.796
2025-07-02 06:41:16.796         # pump out diffs from after the synch point
2025-07-02 06:41:16.796 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.796
2025-07-02 06:41:16.796 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.796 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.796
2025-07-02 06:41:16.796 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.796 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.796 alo = 119, ahi = 1101
2025-07-02 06:41:16.796 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.796 blo = 119, bhi = 1101
2025-07-02 06:41:16.796
2025-07-02 06:41:16.796     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.796         g = []
2025-07-02 06:41:16.796         if alo < ahi:
2025-07-02 06:41:16.796             if blo < bhi:
2025-07-02 06:41:16.796                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.796             else:
2025-07-02 06:41:16.797                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.797         elif blo < bhi:
2025-07-02 06:41:16.797             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.797
2025-07-02 06:41:16.797 >       yield from g
2025-07-02 06:41:16.797
2025-07-02 06:41:16.797 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.797 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.797
2025-07-02 06:41:16.797 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.797 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.797 alo = 119, ahi = 1101
2025-07-02 06:41:16.797 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.797 blo = 119, bhi = 1101
2025-07-02 06:41:16.797
2025-07-02 06:41:16.797     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.797         r"""
2025-07-02 06:41:16.797         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.797         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.798         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.798         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.798
2025-07-02 06:41:16.798         Example:
2025-07-02 06:41:16.798
2025-07-02 06:41:16.798         >>> d = Differ()
2025-07-02 06:41:16.798         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.798         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.798         >>> print(''.join(results), end="")
2025-07-02 06:41:16.798         - abcDefghiJkl
2025-07-02 06:41:16.798         + abcdefGhijkl
2025-07-02 06:41:16.798         """
2025-07-02 06:41:16.798
2025-07-02 06:41:16.798         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.798         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.798         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.798         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.799         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.799
2025-07-02 06:41:16.799         # search for the pair that matches best without being identical
2025-07-02 06:41:16.799         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.799         # on junk -- unless we have to)
2025-07-02 06:41:16.799         for j in range(blo, bhi):
2025-07-02 06:41:16.799             bj = b[j]
2025-07-02 06:41:16.799             cruncher.set_seq2(bj)
2025-07-02 06:41:16.799             for i in range(alo, ahi):
2025-07-02 06:41:16.799                 ai = a[i]
2025-07-02 06:41:16.799                 if ai == bj:
2025-07-02 06:41:16.799                     if eqi is None:
2025-07-02 06:41:16.799                         eqi, eqj = i, j
2025-07-02 06:41:16.799                     continue
2025-07-02 06:41:16.799                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.799                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.799                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.799                 # compares by a factor of 3.
2025-07-02 06:41:16.799                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.800                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.800                 # of the computation is cached by cruncher
2025-07-02 06:41:16.800                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.800                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.800                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.800                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.800         if best_ratio < cutoff:
2025-07-02 06:41:16.800             # no non-identical "pretty close" pair
2025-07-02 06:41:16.800             if eqi is None:
2025-07-02 06:41:16.800                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.800                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.800                 return
2025-07-02 06:41:16.800             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.800             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.800         else:
2025-07-02 06:41:16.800             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.800             eqi = None
2025-07-02 06:41:16.800
2025-07-02 06:41:16.800         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.801         # identical
2025-07-02 06:41:16.801
2025-07-02 06:41:16.801         # pump out diffs from before the synch point
2025-07-02 06:41:16.801         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.801
2025-07-02 06:41:16.801         # do intraline marking on the synch pair
2025-07-02 06:41:16.801         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.801         if eqi is None:
2025-07-02 06:41:16.801             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.801             atags = btags = ""
2025-07-02 06:41:16.801             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.801             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.801                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.801                 if tag == 'replace':
2025-07-02 06:41:16.801                     atags += '^' * la
2025-07-02 06:41:16.801                     btags += '^' * lb
2025-07-02 06:41:16.801                 elif tag == 'delete':
2025-07-02 06:41:16.801                     atags += '-' * la
2025-07-02 06:41:16.801                 elif tag == 'insert':
2025-07-02 06:41:16.801                     btags += '+' * lb
2025-07-02 06:41:16.801                 elif tag == 'equal':
2025-07-02 06:41:16.802                     atags += ' ' * la
2025-07-02 06:41:16.802                     btags += ' ' * lb
2025-07-02 06:41:16.802                 else:
2025-07-02 06:41:16.802                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.802             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.802         else:
2025-07-02 06:41:16.802             # the synch pair is identical
2025-07-02 06:41:16.802             yield '  ' + aelt
2025-07-02 06:41:16.802
2025-07-02 06:41:16.802         # pump out diffs from after the synch point
2025-07-02 06:41:16.802 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.802
2025-07-02 06:41:16.802 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.802 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.802
2025-07-02 06:41:16.802 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.802 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.802 alo = 120, ahi = 1101
2025-07-02 06:41:16.802 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.803 blo = 120, bhi = 1101
2025-07-02 06:41:16.803
2025-07-02 06:41:16.803     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.803         g = []
2025-07-02 06:41:16.803         if alo < ahi:
2025-07-02 06:41:16.803             if blo < bhi:
2025-07-02 06:41:16.803                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.803             else:
2025-07-02 06:41:16.803                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.803         elif blo < bhi:
2025-07-02 06:41:16.803             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.803
2025-07-02 06:41:16.803 >       yield from g
2025-07-02 06:41:16.803
2025-07-02 06:41:16.803 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.803 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.803
2025-07-02 06:41:16.803 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.803 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.803 alo = 120, ahi = 1101
2025-07-02 06:41:16.803 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.804 blo = 120, bhi = 1101
2025-07-02 06:41:16.804
2025-07-02 06:41:16.804     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.804         r"""
2025-07-02 06:41:16.804         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.804         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.804         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.804         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.804
2025-07-02 06:41:16.804         Example:
2025-07-02 06:41:16.804
2025-07-02 06:41:16.804         >>> d = Differ()
2025-07-02 06:41:16.804         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.804         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.804         >>> print(''.join(results), end="")
2025-07-02 06:41:16.804         - abcDefghiJkl
2025-07-02 06:41:16.804         + abcdefGhijkl
2025-07-02 06:41:16.804         """
2025-07-02 06:41:16.805
2025-07-02 06:41:16.805         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.805         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.805         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.805         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.805         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.805
2025-07-02 06:41:16.805         # search for the pair that matches best without being identical
2025-07-02 06:41:16.805         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.805         # on junk -- unless we have to)
2025-07-02 06:41:16.805         for j in range(blo, bhi):
2025-07-02 06:41:16.805             bj = b[j]
2025-07-02 06:41:16.805             cruncher.set_seq2(bj)
2025-07-02 06:41:16.805             for i in range(alo, ahi):
2025-07-02 06:41:16.805                 ai = a[i]
2025-07-02 06:41:16.805                 if ai == bj:
2025-07-02 06:41:16.805                     if eqi is None:
2025-07-02 06:41:16.805                         eqi, eqj = i, j
2025-07-02 06:41:16.805                     continue
2025-07-02 06:41:16.805                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.805                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.806                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.806                 # compares by a factor of 3.
2025-07-02 06:41:16.806                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.806                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.806                 # of the computation is cached by cruncher
2025-07-02 06:41:16.806                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.806                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.806                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.806                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.806         if best_ratio < cutoff:
2025-07-02 06:41:16.806             # no non-identical "pretty close" pair
2025-07-02 06:41:16.806             if eqi is None:
2025-07-02 06:41:16.806                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.806                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.806                 return
2025-07-02 06:41:16.806             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.806             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.806         else:
2025-07-02 06:41:16.807             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.807             eqi = None
2025-07-02 06:41:16.807
2025-07-02 06:41:16.807         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.807         # identical
2025-07-02 06:41:16.807
2025-07-02 06:41:16.807         # pump out diffs from before the synch point
2025-07-02 06:41:16.807         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.807
2025-07-02 06:41:16.807         # do intraline marking on the synch pair
2025-07-02 06:41:16.807         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.807         if eqi is None:
2025-07-02 06:41:16.807             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.807             atags = btags = ""
2025-07-02 06:41:16.807             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.807             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.807                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.807                 if tag == 'replace':
2025-07-02 06:41:16.807                     atags += '^' * la
2025-07-02 06:41:16.808                     btags += '^' * lb
2025-07-02 06:41:16.808                 elif tag == 'delete':
2025-07-02 06:41:16.808                     atags += '-' * la
2025-07-02 06:41:16.808                 elif tag == 'insert':
2025-07-02 06:41:16.808                     btags += '+' * lb
2025-07-02 06:41:16.808                 elif tag == 'equal':
2025-07-02 06:41:16.808                     atags += ' ' * la
2025-07-02 06:41:16.808                     btags += ' ' * lb
2025-07-02 06:41:16.808                 else:
2025-07-02 06:41:16.808                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.808             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.808         else:
2025-07-02 06:41:16.808             # the synch pair is identical
2025-07-02 06:41:16.808             yield '  ' + aelt
2025-07-02 06:41:16.808
2025-07-02 06:41:16.808         # pump out diffs from after the synch point
2025-07-02 06:41:16.808 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.808
2025-07-02 06:41:16.808 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.809 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.809
2025-07-02 06:41:16.809 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.809 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.809 alo = 121, ahi = 1101
2025-07-02 06:41:16.809 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.809 blo = 121, bhi = 1101
2025-07-02 06:41:16.809
2025-07-02 06:41:16.809     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.809         g = []
2025-07-02 06:41:16.809         if alo < ahi:
2025-07-02 06:41:16.809             if blo < bhi:
2025-07-02 06:41:16.809                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.809             else:
2025-07-02 06:41:16.809                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.809         elif blo < bhi:
2025-07-02 06:41:16.809             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.809
2025-07-02 06:41:16.809 >       yield from g
2025-07-02 06:41:16.810
2025-07-02 06:41:16.810 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.810 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.810
2025-07-02 06:41:16.810 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.810 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.810 alo = 121, ahi = 1101
2025-07-02 06:41:16.810 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.810 blo = 121, bhi = 1101
2025-07-02 06:41:16.810
2025-07-02 06:41:16.810     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.810         r"""
2025-07-02 06:41:16.810         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.810         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.810         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.810         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.810
2025-07-02 06:41:16.810         Example:
2025-07-02 06:41:16.811
2025-07-02 06:41:16.811         >>> d = Differ()
2025-07-02 06:41:16.811         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.811         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.811         >>> print(''.join(results), end="")
2025-07-02 06:41:16.811         - abcDefghiJkl
2025-07-02 06:41:16.811         + abcdefGhijkl
2025-07-02 06:41:16.811         """
2025-07-02 06:41:16.811
2025-07-02 06:41:16.811         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.811         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.811         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.811         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.811         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.811
2025-07-02 06:41:16.811         # search for the pair that matches best without being identical
2025-07-02 06:41:16.811         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.811         # on junk -- unless we have to)
2025-07-02 06:41:16.812         for j in range(blo, bhi):
2025-07-02 06:41:16.812             bj = b[j]
2025-07-02 06:41:16.812             cruncher.set_seq2(bj)
2025-07-02 06:41:16.812             for i in range(alo, ahi):
2025-07-02 06:41:16.812                 ai = a[i]
2025-07-02 06:41:16.812                 if ai == bj:
2025-07-02 06:41:16.812                     if eqi is None:
2025-07-02 06:41:16.812                         eqi, eqj = i, j
2025-07-02 06:41:16.812                     continue
2025-07-02 06:41:16.812                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.812                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.812                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.812                 # compares by a factor of 3.
2025-07-02 06:41:16.812                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.812                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.812                 # of the computation is cached by cruncher
2025-07-02 06:41:16.812                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.812                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.812                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.813                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.813         if best_ratio < cutoff:
2025-07-02 06:41:16.813             # no non-identical "pretty close" pair
2025-07-02 06:41:16.813             if eqi is None:
2025-07-02 06:41:16.813                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.813                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.813                 return
2025-07-02 06:41:16.813             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.813             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.813         else:
2025-07-02 06:41:16.813             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.813             eqi = None
2025-07-02 06:41:16.813
2025-07-02 06:41:16.813         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.813         # identical
2025-07-02 06:41:16.813
2025-07-02 06:41:16.813         # pump out diffs from before the synch point
2025-07-02 06:41:16.813         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.813
2025-07-02 06:41:16.813         # do intraline marking on the synch pair
2025-07-02 06:41:16.814         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.814         if eqi is None:
2025-07-02 06:41:16.814             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.814             atags = btags = ""
2025-07-02 06:41:16.814             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.814             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.814                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.814                 if tag == 'replace':
2025-07-02 06:41:16.814                     atags += '^' * la
2025-07-02 06:41:16.814                     btags += '^' * lb
2025-07-02 06:41:16.814                 elif tag == 'delete':
2025-07-02 06:41:16.814                     atags += '-' * la
2025-07-02 06:41:16.814                 elif tag == 'insert':
2025-07-02 06:41:16.814                     btags += '+' * lb
2025-07-02 06:41:16.814                 elif tag == 'equal':
2025-07-02 06:41:16.814                     atags += ' ' * la
2025-07-02 06:41:16.814                     btags += ' ' * lb
2025-07-02 06:41:16.814                 else:
2025-07-02 06:41:16.814                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.814             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.815         else:
2025-07-02 06:41:16.815             # the synch pair is identical
2025-07-02 06:41:16.815             yield '  ' + aelt
2025-07-02 06:41:16.815
2025-07-02 06:41:16.815         # pump out diffs from after the synch point
2025-07-02 06:41:16.815 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.815
2025-07-02 06:41:16.815 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.815 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.815
2025-07-02 06:41:16.815 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.815 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.815 alo = 122, ahi = 1101
2025-07-02 06:41:16.815 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.815 blo = 122, bhi = 1101
2025-07-02 06:41:16.815
2025-07-02 06:41:16.815     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.815         g = []
2025-07-02 06:41:16.815         if alo < ahi:
2025-07-02 06:41:16.816             if blo < bhi:
2025-07-02 06:41:16.816                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.816             else:
2025-07-02 06:41:16.816                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.816         elif blo < bhi:
2025-07-02 06:41:16.816             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.816
2025-07-02 06:41:16.816 >       yield from g
2025-07-02 06:41:16.816
2025-07-02 06:41:16.816 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.816 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.816
2025-07-02 06:41:16.816 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.816 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.816 alo = 122, ahi = 1101
2025-07-02 06:41:16.816 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.816 blo = 122, bhi = 1101
2025-07-02 06:41:16.816
2025-07-02 06:41:16.816     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.817         r"""
2025-07-02 06:41:16.817         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.817         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.817         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.817         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.817
2025-07-02 06:41:16.817         Example:
2025-07-02 06:41:16.817
2025-07-02 06:41:16.817         >>> d = Differ()
2025-07-02 06:41:16.817         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.817         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.817         >>> print(''.join(results), end="")
2025-07-02 06:41:16.817         - abcDefghiJkl
2025-07-02 06:41:16.817         + abcdefGhijkl
2025-07-02 06:41:16.817         """
2025-07-02 06:41:16.817
2025-07-02 06:41:16.817         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.818         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.818         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.818         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.818         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.818
2025-07-02 06:41:16.818         # search for the pair that matches best without being identical
2025-07-02 06:41:16.818         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.818         # on junk -- unless we have to)
2025-07-02 06:41:16.818         for j in range(blo, bhi):
2025-07-02 06:41:16.818             bj = b[j]
2025-07-02 06:41:16.818             cruncher.set_seq2(bj)
2025-07-02 06:41:16.818             for i in range(alo, ahi):
2025-07-02 06:41:16.818                 ai = a[i]
2025-07-02 06:41:16.818                 if ai == bj:
2025-07-02 06:41:16.818                     if eqi is None:
2025-07-02 06:41:16.818                         eqi, eqj = i, j
2025-07-02 06:41:16.818                     continue
2025-07-02 06:41:16.818                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.818                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.818                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.818                 # compares by a factor of 3.
2025-07-02 06:41:16.819                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.819                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.819                 # of the computation is cached by cruncher
2025-07-02 06:41:16.819                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.819                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.819                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.819                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.819         if best_ratio < cutoff:
2025-07-02 06:41:16.819             # no non-identical "pretty close" pair
2025-07-02 06:41:16.819             if eqi is None:
2025-07-02 06:41:16.819                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.819                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.819                 return
2025-07-02 06:41:16.819             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.819             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.819         else:
2025-07-02 06:41:16.819             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.819             eqi = None
2025-07-02 06:41:16.819
2025-07-02 06:41:16.819         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.820         # identical
2025-07-02 06:41:16.820
2025-07-02 06:41:16.820         # pump out diffs from before the synch point
2025-07-02 06:41:16.820         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.820
2025-07-02 06:41:16.820         # do intraline marking on the synch pair
2025-07-02 06:41:16.820         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.820         if eqi is None:
2025-07-02 06:41:16.820             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.820             atags = btags = ""
2025-07-02 06:41:16.820             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.820             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.820                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.820                 if tag == 'replace':
2025-07-02 06:41:16.820                     atags += '^' * la
2025-07-02 06:41:16.820                     btags += '^' * lb
2025-07-02 06:41:16.820                 elif tag == 'delete':
2025-07-02 06:41:16.820                     atags += '-' * la
2025-07-02 06:41:16.820                 elif tag == 'insert':
2025-07-02 06:41:16.820                     btags += '+' * lb
2025-07-02 06:41:16.821                 elif tag == 'equal':
2025-07-02 06:41:16.821                     atags += ' ' * la
2025-07-02 06:41:16.821                     btags += ' ' * lb
2025-07-02 06:41:16.821                 else:
2025-07-02 06:41:16.821                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.821             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.821         else:
2025-07-02 06:41:16.821             # the synch pair is identical
2025-07-02 06:41:16.821             yield '  ' + aelt
2025-07-02 06:41:16.821
2025-07-02 06:41:16.821         # pump out diffs from after the synch point
2025-07-02 06:41:16.821 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.821
2025-07-02 06:41:16.821 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.821 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.821
2025-07-02 06:41:16.821 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.821 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.821 alo = 123, ahi = 1101
2025-07-02 06:41:16.821 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.822 blo = 123, bhi = 1101
2025-07-02 06:41:16.822
2025-07-02 06:41:16.822     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.822         g = []
2025-07-02 06:41:16.822         if alo < ahi:
2025-07-02 06:41:16.822             if blo < bhi:
2025-07-02 06:41:16.822                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.822             else:
2025-07-02 06:41:16.822                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.822         elif blo < bhi:
2025-07-02 06:41:16.822             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.822
2025-07-02 06:41:16.822 >       yield from g
2025-07-02 06:41:16.822
2025-07-02 06:41:16.822 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.822 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.822
2025-07-02 06:41:16.822 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.823 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.823 alo = 123, ahi = 1101
2025-07-02 06:41:16.823 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.823 blo = 123, bhi = 1101
2025-07-02 06:41:16.823
2025-07-02 06:41:16.823     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.823         r"""
2025-07-02 06:41:16.823         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.823         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.823         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.823         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.823
2025-07-02 06:41:16.823         Example:
2025-07-02 06:41:16.823
2025-07-02 06:41:16.823         >>> d = Differ()
2025-07-02 06:41:16.823         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.823         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.823         >>> print(''.join(results), end="")
2025-07-02 06:41:16.824         - abcDefghiJkl
2025-07-02 06:41:16.824         + abcdefGhijkl
2025-07-02 06:41:16.824         """
2025-07-02 06:41:16.824
2025-07-02 06:41:16.824         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.824         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.824         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.824         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.824         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.824
2025-07-02 06:41:16.824         # search for the pair that matches best without being identical
2025-07-02 06:41:16.824         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.824         # on junk -- unless we have to)
2025-07-02 06:41:16.824         for j in range(blo, bhi):
2025-07-02 06:41:16.824             bj = b[j]
2025-07-02 06:41:16.824             cruncher.set_seq2(bj)
2025-07-02 06:41:16.825             for i in range(alo, ahi):
2025-07-02 06:41:16.825                 ai = a[i]
2025-07-02 06:41:16.825                 if ai == bj:
2025-07-02 06:41:16.825                     if eqi is None:
2025-07-02 06:41:16.825                         eqi, eqj = i, j
2025-07-02 06:41:16.825                     continue
2025-07-02 06:41:16.825                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.825                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.825                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.825                 # compares by a factor of 3.
2025-07-02 06:41:16.825                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.825                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.825                 # of the computation is cached by cruncher
2025-07-02 06:41:16.825                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.825                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.825                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.825                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.825         if best_ratio < cutoff:
2025-07-02 06:41:16.825             # no non-identical "pretty close" pair
2025-07-02 06:41:16.826             if eqi is None:
2025-07-02 06:41:16.826                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.826                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.826                 return
2025-07-02 06:41:16.826             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.826             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.826         else:
2025-07-02 06:41:16.826             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.826             eqi = None
2025-07-02 06:41:16.826
2025-07-02 06:41:16.826         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.826         # identical
2025-07-02 06:41:16.826
2025-07-02 06:41:16.826         # pump out diffs from before the synch point
2025-07-02 06:41:16.826         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.826
2025-07-02 06:41:16.826         # do intraline marking on the synch pair
2025-07-02 06:41:16.826         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.826         if eqi is None:
2025-07-02 06:41:16.826             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.827             atags = btags = ""
2025-07-02 06:41:16.827             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.827             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.827                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.827                 if tag == 'replace':
2025-07-02 06:41:16.827                     atags += '^' * la
2025-07-02 06:41:16.827                     btags += '^' * lb
2025-07-02 06:41:16.827                 elif tag == 'delete':
2025-07-02 06:41:16.827                     atags += '-' * la
2025-07-02 06:41:16.827                 elif tag == 'insert':
2025-07-02 06:41:16.827                     btags += '+' * lb
2025-07-02 06:41:16.827                 elif tag == 'equal':
2025-07-02 06:41:16.827                     atags += ' ' * la
2025-07-02 06:41:16.827                     btags += ' ' * lb
2025-07-02 06:41:16.827                 else:
2025-07-02 06:41:16.827                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.827             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.827         else:
2025-07-02 06:41:16.827             # the synch pair is identical
2025-07-02 06:41:16.827             yield '  ' + aelt
2025-07-02 06:41:16.828
2025-07-02 06:41:16.828         # pump out diffs from after the synch point
2025-07-02 06:41:16.828 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.828
2025-07-02 06:41:16.828 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.828 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.828
2025-07-02 06:41:16.828 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.828 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.828 alo = 124, ahi = 1101
2025-07-02 06:41:16.828 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.828 blo = 124, bhi = 1101
2025-07-02 06:41:16.828
2025-07-02 06:41:16.828     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.828         g = []
2025-07-02 06:41:16.828         if alo < ahi:
2025-07-02 06:41:16.828             if blo < bhi:
2025-07-02 06:41:16.828                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.828             else:
2025-07-02 06:41:16.829                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.829         elif blo < bhi:
2025-07-02 06:41:16.829             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.829
2025-07-02 06:41:16.829 >       yield from g
2025-07-02 06:41:16.829
2025-07-02 06:41:16.829 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.829 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.829
2025-07-02 06:41:16.829 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.829 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.829 alo = 124, ahi = 1101
2025-07-02 06:41:16.829 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.829 blo = 124, bhi = 1101
2025-07-02 06:41:16.829
2025-07-02 06:41:16.829     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.829         r"""
2025-07-02 06:41:16.829         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.829         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.829         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.830         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.830
2025-07-02 06:41:16.830         Example:
2025-07-02 06:41:16.830
2025-07-02 06:41:16.830         >>> d = Differ()
2025-07-02 06:41:16.830         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.830         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.830         >>> print(''.join(results), end="")
2025-07-02 06:41:16.830         - abcDefghiJkl
2025-07-02 06:41:16.830         + abcdefGhijkl
2025-07-02 06:41:16.830         """
2025-07-02 06:41:16.830
2025-07-02 06:41:16.830         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.830         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.830         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.830         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.830         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.830
2025-07-02 06:41:16.831         # search for the pair that matches best without being identical
2025-07-02 06:41:16.831         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.831         # on junk -- unless we have to)
2025-07-02 06:41:16.831         for j in range(blo, bhi):
2025-07-02 06:41:16.831             bj = b[j]
2025-07-02 06:41:16.831             cruncher.set_seq2(bj)
2025-07-02 06:41:16.831             for i in range(alo, ahi):
2025-07-02 06:41:16.831                 ai = a[i]
2025-07-02 06:41:16.831                 if ai == bj:
2025-07-02 06:41:16.831                     if eqi is None:
2025-07-02 06:41:16.831                         eqi, eqj = i, j
2025-07-02 06:41:16.831                     continue
2025-07-02 06:41:16.831                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.831                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.831                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.831                 # compares by a factor of 3.
2025-07-02 06:41:16.831                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.831                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.831                 # of the computation is cached by cruncher
2025-07-02 06:41:16.831                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.832                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.832                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.832                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.832         if best_ratio < cutoff:
2025-07-02 06:41:16.832             # no non-identical "pretty close" pair
2025-07-02 06:41:16.832             if eqi is None:
2025-07-02 06:41:16.832                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.832                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.832                 return
2025-07-02 06:41:16.832             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.832             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.832         else:
2025-07-02 06:41:16.832             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.832             eqi = None
2025-07-02 06:41:16.832
2025-07-02 06:41:16.832         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.832         # identical
2025-07-02 06:41:16.832
2025-07-02 06:41:16.832         # pump out diffs from before the synch point
2025-07-02 06:41:16.832         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.833
2025-07-02 06:41:16.833         # do intraline marking on the synch pair
2025-07-02 06:41:16.833         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.833         if eqi is None:
2025-07-02 06:41:16.833             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.833             atags = btags = ""
2025-07-02 06:41:16.833             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.833             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.833                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.833                 if tag == 'replace':
2025-07-02 06:41:16.833                     atags += '^' * la
2025-07-02 06:41:16.833                     btags += '^' * lb
2025-07-02 06:41:16.833                 elif tag == 'delete':
2025-07-02 06:41:16.833                     atags += '-' * la
2025-07-02 06:41:16.833                 elif tag == 'insert':
2025-07-02 06:41:16.833                     btags += '+' * lb
2025-07-02 06:41:16.833                 elif tag == 'equal':
2025-07-02 06:41:16.833                     atags += ' ' * la
2025-07-02 06:41:16.834                     btags += ' ' * lb
2025-07-02 06:41:16.834                 else:
2025-07-02 06:41:16.834                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.834             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.834         else:
2025-07-02 06:41:16.834             # the synch pair is identical
2025-07-02 06:41:16.834             yield '  ' + aelt
2025-07-02 06:41:16.834
2025-07-02 06:41:16.834         # pump out diffs from after the synch point
2025-07-02 06:41:16.834 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.834
2025-07-02 06:41:16.834 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.834 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.834
2025-07-02 06:41:16.834 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.834 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.834 alo = 125, ahi = 1101
2025-07-02 06:41:16.834 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.834 blo = 125, bhi = 1101
2025-07-02 06:41:16.835
2025-07-02 06:41:16.835     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.835         g = []
2025-07-02 06:41:16.835         if alo < ahi:
2025-07-02 06:41:16.835             if blo < bhi:
2025-07-02 06:41:16.835                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.835             else:
2025-07-02 06:41:16.835                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.835         elif blo < bhi:
2025-07-02 06:41:16.835             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.835
2025-07-02 06:41:16.835 >       yield from g
2025-07-02 06:41:16.835
2025-07-02 06:41:16.835 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.835 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.835
2025-07-02 06:41:16.835 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.835 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.835 alo = 125, ahi = 1101
2025-07-02 06:41:16.835 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.836 blo = 125, bhi = 1101
2025-07-02 06:41:16.836
2025-07-02 06:41:16.836     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.836         r"""
2025-07-02 06:41:16.836         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.836         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.836         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.836         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.836
2025-07-02 06:41:16.836         Example:
2025-07-02 06:41:16.836
2025-07-02 06:41:16.836         >>> d = Differ()
2025-07-02 06:41:16.836         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.836         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.836         >>> print(''.join(results), end="")
2025-07-02 06:41:16.836         - abcDefghiJkl
2025-07-02 06:41:16.836         + abcdefGhijkl
2025-07-02 06:41:16.837         """
2025-07-02 06:41:16.837
2025-07-02 06:41:16.837         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.837         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.837         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.837         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.837         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.837
2025-07-02 06:41:16.837         # search for the pair that matches best without being identical
2025-07-02 06:41:16.837         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.837         # on junk -- unless we have to)
2025-07-02 06:41:16.837         for j in range(blo, bhi):
2025-07-02 06:41:16.837             bj = b[j]
2025-07-02 06:41:16.837             cruncher.set_seq2(bj)
2025-07-02 06:41:16.837             for i in range(alo, ahi):
2025-07-02 06:41:16.837                 ai = a[i]
2025-07-02 06:41:16.837                 if ai == bj:
2025-07-02 06:41:16.837                     if eqi is None:
2025-07-02 06:41:16.837                         eqi, eqj = i, j
2025-07-02 06:41:16.837                     continue
2025-07-02 06:41:16.837                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.838                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.838                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.838                 # compares by a factor of 3.
2025-07-02 06:41:16.838                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.838                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.838                 # of the computation is cached by cruncher
2025-07-02 06:41:16.838                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.838                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.838                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.838                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.838         if best_ratio < cutoff:
2025-07-02 06:41:16.838             # no non-identical "pretty close" pair
2025-07-02 06:41:16.838             if eqi is None:
2025-07-02 06:41:16.838                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.838                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.838                 return
2025-07-02 06:41:16.838             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.838             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.838         else:
2025-07-02 06:41:16.838             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.839             eqi = None
2025-07-02 06:41:16.839
2025-07-02 06:41:16.839         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.839         # identical
2025-07-02 06:41:16.839
2025-07-02 06:41:16.839         # pump out diffs from before the synch point
2025-07-02 06:41:16.839         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.839
2025-07-02 06:41:16.839         # do intraline marking on the synch pair
2025-07-02 06:41:16.839         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.839         if eqi is None:
2025-07-02 06:41:16.839             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.839             atags = btags = ""
2025-07-02 06:41:16.839             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.839             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.839                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.839                 if tag == 'replace':
2025-07-02 06:41:16.840                     atags += '^' * la
2025-07-02 06:41:16.840                     btags += '^' * lb
2025-07-02 06:41:16.840                 elif tag == 'delete':
2025-07-02 06:41:16.840                     atags += '-' * la
2025-07-02 06:41:16.840                 elif tag == 'insert':
2025-07-02 06:41:16.840                     btags += '+' * lb
2025-07-02 06:41:16.840                 elif tag == 'equal':
2025-07-02 06:41:16.840                     atags += ' ' * la
2025-07-02 06:41:16.840                     btags += ' ' * lb
2025-07-02 06:41:16.840                 else:
2025-07-02 06:41:16.840                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.840             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.840         else:
2025-07-02 06:41:16.840             # the synch pair is identical
2025-07-02 06:41:16.840             yield '  ' + aelt
2025-07-02 06:41:16.840
2025-07-02 06:41:16.840         # pump out diffs from after the synch point
2025-07-02 06:41:16.840 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.840
2025-07-02 06:41:16.840 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.840 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.841
2025-07-02 06:41:16.841 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.841 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.841 alo = 126, ahi = 1101
2025-07-02 06:41:16.841 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.841 blo = 126, bhi = 1101
2025-07-02 06:41:16.841
2025-07-02 06:41:16.841     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.841         g = []
2025-07-02 06:41:16.841         if alo < ahi:
2025-07-02 06:41:16.841             if blo < bhi:
2025-07-02 06:41:16.841                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.841             else:
2025-07-02 06:41:16.841                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.841         elif blo < bhi:
2025-07-02 06:41:16.841             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.841
2025-07-02 06:41:16.841 >       yield from g
2025-07-02 06:41:16.841
2025-07-02 06:41:16.841 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.842 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.842
2025-07-02 06:41:16.842 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.842 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.842 alo = 126, ahi = 1101
2025-07-02 06:41:16.842 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.842 blo = 126, bhi = 1101
2025-07-02 06:41:16.842
2025-07-02 06:41:16.842     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.842         r"""
2025-07-02 06:41:16.842         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.842         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.842         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.842         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.842
2025-07-02 06:41:16.842         Example:
2025-07-02 06:41:16.842
2025-07-02 06:41:16.842         >>> d = Differ()
2025-07-02 06:41:16.843         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.843         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.843         >>> print(''.join(results), end="")
2025-07-02 06:41:16.843         - abcDefghiJkl
2025-07-02 06:41:16.843         + abcdefGhijkl
2025-07-02 06:41:16.843         """
2025-07-02 06:41:16.843
2025-07-02 06:41:16.843         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.843         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.843         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.843         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.843         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.843
2025-07-02 06:41:16.843         # search for the pair that matches best without being identical
2025-07-02 06:41:16.843         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.843         # on junk -- unless we have to)
2025-07-02 06:41:16.843         for j in range(blo, bhi):
2025-07-02 06:41:16.844             bj = b[j]
2025-07-02 06:41:16.844             cruncher.set_seq2(bj)
2025-07-02 06:41:16.844             for i in range(alo, ahi):
2025-07-02 06:41:16.844                 ai = a[i]
2025-07-02 06:41:16.844                 if ai == bj:
2025-07-02 06:41:16.844                     if eqi is None:
2025-07-02 06:41:16.844                         eqi, eqj = i, j
2025-07-02 06:41:16.844                     continue
2025-07-02 06:41:16.844                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.844                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.844                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.844                 # compares by a factor of 3.
2025-07-02 06:41:16.844                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.844                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.844                 # of the computation is cached by cruncher
2025-07-02 06:41:16.844                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.844                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.844                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.844                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.844         if best_ratio < cutoff:
2025-07-02 06:41:16.845             # no non-identical "pretty close" pair
2025-07-02 06:41:16.845             if eqi is None:
2025-07-02 06:41:16.845                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.845                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.845                 return
2025-07-02 06:41:16.845             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.845             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.845         else:
2025-07-02 06:41:16.845             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.845             eqi = None
2025-07-02 06:41:16.845
2025-07-02 06:41:16.845         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.845         # identical
2025-07-02 06:41:16.845
2025-07-02 06:41:16.845         # pump out diffs from before the synch point
2025-07-02 06:41:16.845         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.845
2025-07-02 06:41:16.845         # do intraline marking on the synch pair
2025-07-02 06:41:16.845         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.845         if eqi is None:
2025-07-02 06:41:16.845             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.846             atags = btags = ""
2025-07-02 06:41:16.846             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.846             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.846                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.846                 if tag == 'replace':
2025-07-02 06:41:16.846                     atags += '^' * la
2025-07-02 06:41:16.846                     btags += '^' * lb
2025-07-02 06:41:16.846                 elif tag == 'delete':
2025-07-02 06:41:16.846                     atags += '-' * la
2025-07-02 06:41:16.846                 elif tag == 'insert':
2025-07-02 06:41:16.846                     btags += '+' * lb
2025-07-02 06:41:16.846                 elif tag == 'equal':
2025-07-02 06:41:16.846                     atags += ' ' * la
2025-07-02 06:41:16.846                     btags += ' ' * lb
2025-07-02 06:41:16.846                 else:
2025-07-02 06:41:16.846                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.846             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.846         else:
2025-07-02 06:41:16.846             # the synch pair is identical
2025-07-02 06:41:16.846             yield '  ' + aelt
2025-07-02 06:41:16.847
2025-07-02 06:41:16.847         # pump out diffs from after the synch point
2025-07-02 06:41:16.847 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.847
2025-07-02 06:41:16.847 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.847 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.847
2025-07-02 06:41:16.847 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.847 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.847 alo = 127, ahi = 1101
2025-07-02 06:41:16.847 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.847 blo = 127, bhi = 1101
2025-07-02 06:41:16.847
2025-07-02 06:41:16.847     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.847         g = []
2025-07-02 06:41:16.847         if alo < ahi:
2025-07-02 06:41:16.847             if blo < bhi:
2025-07-02 06:41:16.847                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.847             else:
2025-07-02 06:41:16.847                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.847         elif blo < bhi:
2025-07-02 06:41:16.848             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.848
2025-07-02 06:41:16.848 >       yield from g
2025-07-02 06:41:16.848
2025-07-02 06:41:16.848 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.848 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.848
2025-07-02 06:41:16.848 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.848 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.848 alo = 127, ahi = 1101
2025-07-02 06:41:16.848 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.848 blo = 127, bhi = 1101
2025-07-02 06:41:16.848
2025-07-02 06:41:16.848     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.848         r"""
2025-07-02 06:41:16.848         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.848         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.848         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.848         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.848
2025-07-02 06:41:16.849         Example:
2025-07-02 06:41:16.849
2025-07-02 06:41:16.849         >>> d = Differ()
2025-07-02 06:41:16.849         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.849         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.849         >>> print(''.join(results), end="")
2025-07-02 06:41:16.849         - abcDefghiJkl
2025-07-02 06:41:16.849         + abcdefGhijkl
2025-07-02 06:41:16.849         """
2025-07-02 06:41:16.849
2025-07-02 06:41:16.849         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.849         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.849         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.849         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.849         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.849
2025-07-02 06:41:16.849         # search for the pair that matches best without being identical
2025-07-02 06:41:16.849         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.850         # on junk -- unless we have to)
2025-07-02 06:41:16.850         for j in range(blo, bhi):
2025-07-02 06:41:16.850             bj = b[j]
2025-07-02 06:41:16.850             cruncher.set_seq2(bj)
2025-07-02 06:41:16.850             for i in range(alo, ahi):
2025-07-02 06:41:16.850                 ai = a[i]
2025-07-02 06:41:16.850                 if ai == bj:
2025-07-02 06:41:16.850                     if eqi is None:
2025-07-02 06:41:16.850                         eqi, eqj = i, j
2025-07-02 06:41:16.850                     continue
2025-07-02 06:41:16.850                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.850                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.850                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.850                 # compares by a factor of 3.
2025-07-02 06:41:16.850                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.850                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.850                 # of the computation is cached by cruncher
2025-07-02 06:41:16.850                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.850                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.850                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.851                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.851         if best_ratio < cutoff:
2025-07-02 06:41:16.851             # no non-identical "pretty close" pair
2025-07-02 06:41:16.851             if eqi is None:
2025-07-02 06:41:16.851                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.851                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.851                 return
2025-07-02 06:41:16.851             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.851             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.851         else:
2025-07-02 06:41:16.851             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.851             eqi = None
2025-07-02 06:41:16.851
2025-07-02 06:41:16.851         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.851         # identical
2025-07-02 06:41:16.851
2025-07-02 06:41:16.851         # pump out diffs from before the synch point
2025-07-02 06:41:16.851         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.852
2025-07-02 06:41:16.852         # do intraline marking on the synch pair
2025-07-02 06:41:16.852         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.852         if eqi is None:
2025-07-02 06:41:16.852             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.852             atags = btags = ""
2025-07-02 06:41:16.852             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.852             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.852                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.852                 if tag == 'replace':
2025-07-02 06:41:16.852                     atags += '^' * la
2025-07-02 06:41:16.852                     btags += '^' * lb
2025-07-02 06:41:16.852                 elif tag == 'delete':
2025-07-02 06:41:16.852                     atags += '-' * la
2025-07-02 06:41:16.852                 elif tag == 'insert':
2025-07-02 06:41:16.852                     btags += '+' * lb
2025-07-02 06:41:16.852                 elif tag == 'equal':
2025-07-02 06:41:16.852                     atags += ' ' * la
2025-07-02 06:41:16.852                     btags += ' ' * lb
2025-07-02 06:41:16.852                 else:
2025-07-02 06:41:16.853                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.853             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.853         else:
2025-07-02 06:41:16.853             # the synch pair is identical
2025-07-02 06:41:16.853             yield '  ' + aelt
2025-07-02 06:41:16.853
2025-07-02 06:41:16.853         # pump out diffs from after the synch point
2025-07-02 06:41:16.853 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.853
2025-07-02 06:41:16.853 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.853 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.853
2025-07-02 06:41:16.853 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.853 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.853 alo = 128, ahi = 1101
2025-07-02 06:41:16.853 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.853 blo = 128, bhi = 1101
2025-07-02 06:41:16.853
2025-07-02 06:41:16.853     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.853         g = []
2025-07-02 06:41:16.854         if alo < ahi:
2025-07-02 06:41:16.854             if blo < bhi:
2025-07-02 06:41:16.854                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.854             else:
2025-07-02 06:41:16.854                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.854         elif blo < bhi:
2025-07-02 06:41:16.854             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.854
2025-07-02 06:41:16.854 >       yield from g
2025-07-02 06:41:16.854
2025-07-02 06:41:16.854 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.854 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.854
2025-07-02 06:41:16.854 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.854 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.854 alo = 128, ahi = 1101
2025-07-02 06:41:16.854 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.854 blo = 128, bhi = 1101
2025-07-02 06:41:16.854
2025-07-02 06:41:16.854     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.854         r"""
2025-07-02 06:41:16.855         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.855         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.855         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.855         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.855
2025-07-02 06:41:16.855         Example:
2025-07-02 06:41:16.855
2025-07-02 06:41:16.855         >>> d = Differ()
2025-07-02 06:41:16.855         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.855         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.855         >>> print(''.join(results), end="")
2025-07-02 06:41:16.855         - abcDefghiJkl
2025-07-02 06:41:16.855         + abcdefGhijkl
2025-07-02 06:41:16.855         """
2025-07-02 06:41:16.855
2025-07-02 06:41:16.855         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.856         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.856         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.856         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.856         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.856
2025-07-02 06:41:16.856         # search for the pair that matches best without being identical
2025-07-02 06:41:16.856         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.856         # on junk -- unless we have to)
2025-07-02 06:41:16.856         for j in range(blo, bhi):
2025-07-02 06:41:16.856             bj = b[j]
2025-07-02 06:41:16.856             cruncher.set_seq2(bj)
2025-07-02 06:41:16.856             for i in range(alo, ahi):
2025-07-02 06:41:16.856                 ai = a[i]
2025-07-02 06:41:16.856                 if ai == bj:
2025-07-02 06:41:16.856                     if eqi is None:
2025-07-02 06:41:16.856                         eqi, eqj = i, j
2025-07-02 06:41:16.856                     continue
2025-07-02 06:41:16.856                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.856                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.857                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.857                 # compares by a factor of 3.
2025-07-02 06:41:16.857                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.857                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.857                 # of the computation is cached by cruncher
2025-07-02 06:41:16.857                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.857                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.857                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.857                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.857         if best_ratio < cutoff:
2025-07-02 06:41:16.857             # no non-identical "pretty close" pair
2025-07-02 06:41:16.857             if eqi is None:
2025-07-02 06:41:16.857                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.857                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.857                 return
2025-07-02 06:41:16.857             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.857             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.857         else:
2025-07-02 06:41:16.857             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.858             eqi = None
2025-07-02 06:41:16.858
2025-07-02 06:41:16.858         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.858         # identical
2025-07-02 06:41:16.858
2025-07-02 06:41:16.858         # pump out diffs from before the synch point
2025-07-02 06:41:16.858         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.858
2025-07-02 06:41:16.858         # do intraline marking on the synch pair
2025-07-02 06:41:16.858         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.858         if eqi is None:
2025-07-02 06:41:16.858             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.858             atags = btags = ""
2025-07-02 06:41:16.858             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.858             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.858                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.858                 if tag == 'replace':
2025-07-02 06:41:16.858                     atags += '^' * la
2025-07-02 06:41:16.858                     btags += '^' * lb
2025-07-02 06:41:16.858                 elif tag == 'delete':
2025-07-02 06:41:16.859                     atags += '-' * la
2025-07-02 06:41:16.859                 elif tag == 'insert':
2025-07-02 06:41:16.859                     btags += '+' * lb
2025-07-02 06:41:16.859                 elif tag == 'equal':
2025-07-02 06:41:16.859                     atags += ' ' * la
2025-07-02 06:41:16.859                     btags += ' ' * lb
2025-07-02 06:41:16.859                 else:
2025-07-02 06:41:16.859                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.859             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.859         else:
2025-07-02 06:41:16.859             # the synch pair is identical
2025-07-02 06:41:16.859             yield '  ' + aelt
2025-07-02 06:41:16.859
2025-07-02 06:41:16.859         # pump out diffs from after the synch point
2025-07-02 06:41:16.859 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.859
2025-07-02 06:41:16.859 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.859 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.859
2025-07-02 06:41:16.860 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.860 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.860 alo = 129, ahi = 1101
2025-07-02 06:41:16.860 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.860 blo = 129, bhi = 1101
2025-07-02 06:41:16.860
2025-07-02 06:41:16.860     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.860         g = []
2025-07-02 06:41:16.860         if alo < ahi:
2025-07-02 06:41:16.860             if blo < bhi:
2025-07-02 06:41:16.860                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.860             else:
2025-07-02 06:41:16.860                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.860         elif blo < bhi:
2025-07-02 06:41:16.860             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.860
2025-07-02 06:41:16.860 >       yield from g
2025-07-02 06:41:16.860
2025-07-02 06:41:16.860 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.861 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.861
2025-07-02 06:41:16.861 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.861 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.861 alo = 129, ahi = 1101
2025-07-02 06:41:16.861 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.861 blo = 129, bhi = 1101
2025-07-02 06:41:16.861
2025-07-02 06:41:16.861     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.861         r"""
2025-07-02 06:41:16.861         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.861         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.861         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.861         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.861
2025-07-02 06:41:16.861         Example:
2025-07-02 06:41:16.861
2025-07-02 06:41:16.861         >>> d = Differ()
2025-07-02 06:41:16.862         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.862         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.862         >>> print(''.join(results), end="")
2025-07-02 06:41:16.862         - abcDefghiJkl
2025-07-02 06:41:16.862         + abcdefGhijkl
2025-07-02 06:41:16.862         """
2025-07-02 06:41:16.862
2025-07-02 06:41:16.862         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.862         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.862         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.862         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.862         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.862
2025-07-02 06:41:16.862         # search for the pair that matches best without being identical
2025-07-02 06:41:16.862         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.862         # on junk -- unless we have to)
2025-07-02 06:41:16.862         for j in range(blo, bhi):
2025-07-02 06:41:16.862             bj = b[j]
2025-07-02 06:41:16.863             cruncher.set_seq2(bj)
2025-07-02 06:41:16.863             for i in range(alo, ahi):
2025-07-02 06:41:16.863                 ai = a[i]
2025-07-02 06:41:16.863                 if ai == bj:
2025-07-02 06:41:16.863                     if eqi is None:
2025-07-02 06:41:16.863                         eqi, eqj = i, j
2025-07-02 06:41:16.863                     continue
2025-07-02 06:41:16.863                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.863                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.863                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.863                 # compares by a factor of 3.
2025-07-02 06:41:16.863                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.863                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.863                 # of the computation is cached by cruncher
2025-07-02 06:41:16.863                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.863                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.863                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.863                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.863         if best_ratio < cutoff:
2025-07-02 06:41:16.864             # no non-identical "pretty close" pair
2025-07-02 06:41:16.864             if eqi is None:
2025-07-02 06:41:16.864                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.864                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.864                 return
2025-07-02 06:41:16.864             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.864             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.864         else:
2025-07-02 06:41:16.864             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.864             eqi = None
2025-07-02 06:41:16.864
2025-07-02 06:41:16.864         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.864         # identical
2025-07-02 06:41:16.864
2025-07-02 06:41:16.864         # pump out diffs from before the synch point
2025-07-02 06:41:16.864         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.864
2025-07-02 06:41:16.864         # do intraline marking on the synch pair
2025-07-02 06:41:16.864         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.864         if eqi is None:
2025-07-02 06:41:16.865             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.865             atags = btags = ""
2025-07-02 06:41:16.865             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.865             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.865                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.865                 if tag == 'replace':
2025-07-02 06:41:16.865                     atags += '^' * la
2025-07-02 06:41:16.865                     btags += '^' * lb
2025-07-02 06:41:16.865                 elif tag == 'delete':
2025-07-02 06:41:16.865                     atags += '-' * la
2025-07-02 06:41:16.865                 elif tag == 'insert':
2025-07-02 06:41:16.865                     btags += '+' * lb
2025-07-02 06:41:16.865                 elif tag == 'equal':
2025-07-02 06:41:16.865                     atags += ' ' * la
2025-07-02 06:41:16.865                     btags += ' ' * lb
2025-07-02 06:41:16.865                 else:
2025-07-02 06:41:16.865                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.865             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.865         else:
2025-07-02 06:41:16.865             # the synch pair is identical
2025-07-02 06:41:16.866             yield '  ' + aelt
2025-07-02 06:41:16.866
2025-07-02 06:41:16.866         # pump out diffs from after the synch point
2025-07-02 06:41:16.866 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.866
2025-07-02 06:41:16.866 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.866 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.866
2025-07-02 06:41:16.866 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.866 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.866 alo = 130, ahi = 1101
2025-07-02 06:41:16.866 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.866 blo = 130, bhi = 1101
2025-07-02 06:41:16.866
2025-07-02 06:41:16.866     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.866         g = []
2025-07-02 06:41:16.866         if alo < ahi:
2025-07-02 06:41:16.866             if blo < bhi:
2025-07-02 06:41:16.866                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.867             else:
2025-07-02 06:41:16.867                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.867         elif blo < bhi:
2025-07-02 06:41:16.867             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.867
2025-07-02 06:41:16.867 >       yield from g
2025-07-02 06:41:16.867
2025-07-02 06:41:16.867 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.867 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.867
2025-07-02 06:41:16.867 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.867 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.867 alo = 130, ahi = 1101
2025-07-02 06:41:16.867 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.867 blo = 130, bhi = 1101
2025-07-02 06:41:16.867
2025-07-02 06:41:16.867     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.867         r"""
2025-07-02 06:41:16.867         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.868         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.868         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.868         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.868
2025-07-02 06:41:16.868         Example:
2025-07-02 06:41:16.868
2025-07-02 06:41:16.868         >>> d = Differ()
2025-07-02 06:41:16.868         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.868         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.868         >>> print(''.join(results), end="")
2025-07-02 06:41:16.868         - abcDefghiJkl
2025-07-02 06:41:16.868         + abcdefGhijkl
2025-07-02 06:41:16.868         """
2025-07-02 06:41:16.868
2025-07-02 06:41:16.868         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.868         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.868         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.869         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.869         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.869
2025-07-02 06:41:16.869         # search for the pair that matches best without being identical
2025-07-02 06:41:16.869         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.869         # on junk -- unless we have to)
2025-07-02 06:41:16.869         for j in range(blo, bhi):
2025-07-02 06:41:16.869             bj = b[j]
2025-07-02 06:41:16.869             cruncher.set_seq2(bj)
2025-07-02 06:41:16.869             for i in range(alo, ahi):
2025-07-02 06:41:16.869                 ai = a[i]
2025-07-02 06:41:16.869                 if ai == bj:
2025-07-02 06:41:16.869                     if eqi is None:
2025-07-02 06:41:16.869                         eqi, eqj = i, j
2025-07-02 06:41:16.869                     continue
2025-07-02 06:41:16.869                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.869                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.869                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.870                 # compares by a factor of 3.
2025-07-02 06:41:16.870                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.870                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.870                 # of the computation is cached by cruncher
2025-07-02 06:41:16.870                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.870                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.870                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.870                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.870         if best_ratio < cutoff:
2025-07-02 06:41:16.870             # no non-identical "pretty close" pair
2025-07-02 06:41:16.870             if eqi is None:
2025-07-02 06:41:16.870                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.870                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.870                 return
2025-07-02 06:41:16.870             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.870             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.870         else:
2025-07-02 06:41:16.870             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.870             eqi = None
2025-07-02 06:41:16.871
2025-07-02 06:41:16.871         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.871         # identical
2025-07-02 06:41:16.871
2025-07-02 06:41:16.871         # pump out diffs from before the synch point
2025-07-02 06:41:16.871         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.871
2025-07-02 06:41:16.871         # do intraline marking on the synch pair
2025-07-02 06:41:16.871         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.871         if eqi is None:
2025-07-02 06:41:16.871             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.871             atags = btags = ""
2025-07-02 06:41:16.871             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.871             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.871                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.871                 if tag == 'replace':
2025-07-02 06:41:16.871                     atags += '^' * la
2025-07-02 06:41:16.871                     btags += '^' * lb
2025-07-02 06:41:16.871                 elif tag == 'delete':
2025-07-02 06:41:16.872                     atags += '-' * la
2025-07-02 06:41:16.872                 elif tag == 'insert':
2025-07-02 06:41:16.872                     btags += '+' * lb
2025-07-02 06:41:16.872                 elif tag == 'equal':
2025-07-02 06:41:16.872                     atags += ' ' * la
2025-07-02 06:41:16.872                     btags += ' ' * lb
2025-07-02 06:41:16.872                 else:
2025-07-02 06:41:16.872                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.872             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.872         else:
2025-07-02 06:41:16.872             # the synch pair is identical
2025-07-02 06:41:16.872             yield '  ' + aelt
2025-07-02 06:41:16.872
2025-07-02 06:41:16.872         # pump out diffs from after the synch point
2025-07-02 06:41:16.872 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.872
2025-07-02 06:41:16.872 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.872 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.872
2025-07-02 06:41:16.873 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.873 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.873 alo = 131, ahi = 1101
2025-07-02 06:41:16.873 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.873 blo = 131, bhi = 1101
2025-07-02 06:41:16.873
2025-07-02 06:41:16.873     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.873         g = []
2025-07-02 06:41:16.873         if alo < ahi:
2025-07-02 06:41:16.873             if blo < bhi:
2025-07-02 06:41:16.873                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.873             else:
2025-07-02 06:41:16.873                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.873         elif blo < bhi:
2025-07-02 06:41:16.873             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.873
2025-07-02 06:41:16.873 >       yield from g
2025-07-02 06:41:16.873
2025-07-02 06:41:16.873 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.873 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.874
2025-07-02 06:41:16.874 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.874 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.874 alo = 131, ahi = 1101
2025-07-02 06:41:16.874 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.874 blo = 131, bhi = 1101
2025-07-02 06:41:16.874
2025-07-02 06:41:16.874     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.874         r"""
2025-07-02 06:41:16.874         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.874         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.874         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.874         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.874
2025-07-02 06:41:16.874         Example:
2025-07-02 06:41:16.874
2025-07-02 06:41:16.874         >>> d = Differ()
2025-07-02 06:41:16.874         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.874         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.875         >>> print(''.join(results), end="")
2025-07-02 06:41:16.875         - abcDefghiJkl
2025-07-02 06:41:16.875         + abcdefGhijkl
2025-07-02 06:41:16.875         """
2025-07-02 06:41:16.875
2025-07-02 06:41:16.875         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.875         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.875         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.875         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.875         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.875
2025-07-02 06:41:16.875         # search for the pair that matches best without being identical
2025-07-02 06:41:16.875         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.875         # on junk -- unless we have to)
2025-07-02 06:41:16.875         for j in range(blo, bhi):
2025-07-02 06:41:16.875             bj = b[j]
2025-07-02 06:41:16.875             cruncher.set_seq2(bj)
2025-07-02 06:41:16.875             for i in range(alo, ahi):
2025-07-02 06:41:16.876                 ai = a[i]
2025-07-02 06:41:16.876                 if ai == bj:
2025-07-02 06:41:16.876                     if eqi is None:
2025-07-02 06:41:16.876                         eqi, eqj = i, j
2025-07-02 06:41:16.876                     continue
2025-07-02 06:41:16.876                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.876                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.876                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.876                 # compares by a factor of 3.
2025-07-02 06:41:16.876                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.876                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.876                 # of the computation is cached by cruncher
2025-07-02 06:41:16.876                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.876                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.876                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.876                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.876         if best_ratio < cutoff:
2025-07-02 06:41:16.876             # no non-identical "pretty close" pair
2025-07-02 06:41:16.876             if eqi is None:
2025-07-02 06:41:16.877                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.877                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.877                 return
2025-07-02 06:41:16.877             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.877             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.877         else:
2025-07-02 06:41:16.877             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.877             eqi = None
2025-07-02 06:41:16.877
2025-07-02 06:41:16.877         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.877         # identical
2025-07-02 06:41:16.877
2025-07-02 06:41:16.877         # pump out diffs from before the synch point
2025-07-02 06:41:16.877         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.877
2025-07-02 06:41:16.877         # do intraline marking on the synch pair
2025-07-02 06:41:16.877         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.877         if eqi is None:
2025-07-02 06:41:16.877             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.878             atags = btags = ""
2025-07-02 06:41:16.878             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.878             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.878                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.878                 if tag == 'replace':
2025-07-02 06:41:16.878                     atags += '^' * la
2025-07-02 06:41:16.878                     btags += '^' * lb
2025-07-02 06:41:16.878                 elif tag == 'delete':
2025-07-02 06:41:16.878                     atags += '-' * la
2025-07-02 06:41:16.878                 elif tag == 'insert':
2025-07-02 06:41:16.878                     btags += '+' * lb
2025-07-02 06:41:16.878                 elif tag == 'equal':
2025-07-02 06:41:16.878                     atags += ' ' * la
2025-07-02 06:41:16.878                     btags += ' ' * lb
2025-07-02 06:41:16.878                 else:
2025-07-02 06:41:16.878                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.878             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.878         else:
2025-07-02 06:41:16.878             # the synch pair is identical
2025-07-02 06:41:16.879             yield '  ' + aelt
2025-07-02 06:41:16.879
2025-07-02 06:41:16.879         # pump out diffs from after the synch point
2025-07-02 06:41:16.879 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.879
2025-07-02 06:41:16.879 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.879 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.879
2025-07-02 06:41:16.879 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.879 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.879 alo = 132, ahi = 1101
2025-07-02 06:41:16.879 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.879 blo = 132, bhi = 1101
2025-07-02 06:41:16.879
2025-07-02 06:41:16.879     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.879         g = []
2025-07-02 06:41:16.879         if alo < ahi:
2025-07-02 06:41:16.879             if blo < bhi:
2025-07-02 06:41:16.879                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.880             else:
2025-07-02 06:41:16.880                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.880         elif blo < bhi:
2025-07-02 06:41:16.880             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.880
2025-07-02 06:41:16.880 >       yield from g
2025-07-02 06:41:16.880
2025-07-02 06:41:16.880 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.880 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.880
2025-07-02 06:41:16.880 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.880 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.880 alo = 132, ahi = 1101
2025-07-02 06:41:16.880 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.880 blo = 132, bhi = 1101
2025-07-02 06:41:16.880
2025-07-02 06:41:16.880     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.880         r"""
2025-07-02 06:41:16.880         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.881         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.881         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.881         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.881
2025-07-02 06:41:16.881         Example:
2025-07-02 06:41:16.881
2025-07-02 06:41:16.881         >>> d = Differ()
2025-07-02 06:41:16.881         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.881         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.881         >>> print(''.join(results), end="")
2025-07-02 06:41:16.881         - abcDefghiJkl
2025-07-02 06:41:16.881         + abcdefGhijkl
2025-07-02 06:41:16.881         """
2025-07-02 06:41:16.881
2025-07-02 06:41:16.881         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.881         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.881         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.881         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.882         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.882
2025-07-02 06:41:16.882         # search for the pair that matches best without being identical
2025-07-02 06:41:16.882         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.882         # on junk -- unless we have to)
2025-07-02 06:41:16.882         for j in range(blo, bhi):
2025-07-02 06:41:16.882             bj = b[j]
2025-07-02 06:41:16.882             cruncher.set_seq2(bj)
2025-07-02 06:41:16.882             for i in range(alo, ahi):
2025-07-02 06:41:16.882                 ai = a[i]
2025-07-02 06:41:16.882                 if ai == bj:
2025-07-02 06:41:16.882                     if eqi is None:
2025-07-02 06:41:16.882                         eqi, eqj = i, j
2025-07-02 06:41:16.882                     continue
2025-07-02 06:41:16.882                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.882                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.882                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.882                 # compares by a factor of 3.
2025-07-02 06:41:16.882                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.882                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.883                 # of the computation is cached by cruncher
2025-07-02 06:41:16.883                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.883                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.883                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.883                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.883         if best_ratio < cutoff:
2025-07-02 06:41:16.883             # no non-identical "pretty close" pair
2025-07-02 06:41:16.883             if eqi is None:
2025-07-02 06:41:16.883                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.883                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.883                 return
2025-07-02 06:41:16.883             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.883             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.883         else:
2025-07-02 06:41:16.883             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.883             eqi = None
2025-07-02 06:41:16.883
2025-07-02 06:41:16.883         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.883         # identical
2025-07-02 06:41:16.884
2025-07-02 06:41:16.884         # pump out diffs from before the synch point
2025-07-02 06:41:16.884         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.884
2025-07-02 06:41:16.884         # do intraline marking on the synch pair
2025-07-02 06:41:16.884         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.884         if eqi is None:
2025-07-02 06:41:16.884             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.884             atags = btags = ""
2025-07-02 06:41:16.884             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.884             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.884                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.884                 if tag == 'replace':
2025-07-02 06:41:16.884                     atags += '^' * la
2025-07-02 06:41:16.884                     btags += '^' * lb
2025-07-02 06:41:16.884                 elif tag == 'delete':
2025-07-02 06:41:16.884                     atags += '-' * la
2025-07-02 06:41:16.884                 elif tag == 'insert':
2025-07-02 06:41:16.884                     btags += '+' * lb
2025-07-02 06:41:16.884                 elif tag == 'equal':
2025-07-02 06:41:16.885                     atags += ' ' * la
2025-07-02 06:41:16.885                     btags += ' ' * lb
2025-07-02 06:41:16.885                 else:
2025-07-02 06:41:16.885                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.885             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.885         else:
2025-07-02 06:41:16.885             # the synch pair is identical
2025-07-02 06:41:16.885             yield '  ' + aelt
2025-07-02 06:41:16.885
2025-07-02 06:41:16.885         # pump out diffs from after the synch point
2025-07-02 06:41:16.885 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.885
2025-07-02 06:41:16.885 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.885 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.885
2025-07-02 06:41:16.885 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.885 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.885 alo = 133, ahi = 1101
2025-07-02 06:41:16.885 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.886 blo = 133, bhi = 1101
2025-07-02 06:41:16.886
2025-07-02 06:41:16.886     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.886         g = []
2025-07-02 06:41:16.886         if alo < ahi:
2025-07-02 06:41:16.886             if blo < bhi:
2025-07-02 06:41:16.886                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.886             else:
2025-07-02 06:41:16.886                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.886         elif blo < bhi:
2025-07-02 06:41:16.886             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.886
2025-07-02 06:41:16.886 >       yield from g
2025-07-02 06:41:16.886
2025-07-02 06:41:16.886 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.886 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.886
2025-07-02 06:41:16.886 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.886 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.887 alo = 133, ahi = 1101
2025-07-02 06:41:16.887 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.887 blo = 133, bhi = 1101
2025-07-02 06:41:16.887
2025-07-02 06:41:16.887     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.887         r"""
2025-07-02 06:41:16.887         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.887         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.887         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.887         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.887
2025-07-02 06:41:16.887         Example:
2025-07-02 06:41:16.887
2025-07-02 06:41:16.887         >>> d = Differ()
2025-07-02 06:41:16.887         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.887         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.888         >>> print(''.join(results), end="")
2025-07-02 06:41:16.888         - abcDefghiJkl
2025-07-02 06:41:16.888         + abcdefGhijkl
2025-07-02 06:41:16.888         """
2025-07-02 06:41:16.888
2025-07-02 06:41:16.888         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.888         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.888         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.888         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.888         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.888
2025-07-02 06:41:16.888         # search for the pair that matches best without being identical
2025-07-02 06:41:16.888         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.888         # on junk -- unless we have to)
2025-07-02 06:41:16.888         for j in range(blo, bhi):
2025-07-02 06:41:16.888             bj = b[j]
2025-07-02 06:41:16.888             cruncher.set_seq2(bj)
2025-07-02 06:41:16.889             for i in range(alo, ahi):
2025-07-02 06:41:16.889                 ai = a[i]
2025-07-02 06:41:16.889                 if ai == bj:
2025-07-02 06:41:16.889                     if eqi is None:
2025-07-02 06:41:16.889                         eqi, eqj = i, j
2025-07-02 06:41:16.889                     continue
2025-07-02 06:41:16.889                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.889                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.889                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.889                 # compares by a factor of 3.
2025-07-02 06:41:16.889                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.889                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.889                 # of the computation is cached by cruncher
2025-07-02 06:41:16.889                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.889                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.889                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.889                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.889         if best_ratio < cutoff:
2025-07-02 06:41:16.889             # no non-identical "pretty close" pair
2025-07-02 06:41:16.890             if eqi is None:
2025-07-02 06:41:16.890                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.890                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.890                 return
2025-07-02 06:41:16.890             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.890             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.890         else:
2025-07-02 06:41:16.890             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.890             eqi = None
2025-07-02 06:41:16.890
2025-07-02 06:41:16.890         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.890         # identical
2025-07-02 06:41:16.890
2025-07-02 06:41:16.890         # pump out diffs from before the synch point
2025-07-02 06:41:16.890         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.890
2025-07-02 06:41:16.890         # do intraline marking on the synch pair
2025-07-02 06:41:16.890         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.890         if eqi is None:
2025-07-02 06:41:16.891             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.891             atags = btags = ""
2025-07-02 06:41:16.891             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.891             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.891                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.891                 if tag == 'replace':
2025-07-02 06:41:16.891                     atags += '^' * la
2025-07-02 06:41:16.891                     btags += '^' * lb
2025-07-02 06:41:16.891                 elif tag == 'delete':
2025-07-02 06:41:16.891                     atags += '-' * la
2025-07-02 06:41:16.891                 elif tag == 'insert':
2025-07-02 06:41:16.891                     btags += '+' * lb
2025-07-02 06:41:16.891                 elif tag == 'equal':
2025-07-02 06:41:16.891                     atags += ' ' * la
2025-07-02 06:41:16.891                     btags += ' ' * lb
2025-07-02 06:41:16.891                 else:
2025-07-02 06:41:16.891                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.891             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.892         else:
2025-07-02 06:41:16.892             # the synch pair is identical
2025-07-02 06:41:16.892             yield '  ' + aelt
2025-07-02 06:41:16.892
2025-07-02 06:41:16.892         # pump out diffs from after the synch point
2025-07-02 06:41:16.892 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.892
2025-07-02 06:41:16.892 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.892 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.892
2025-07-02 06:41:16.892 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.892 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.892 alo = 136, ahi = 1101
2025-07-02 06:41:16.892 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.892 blo = 136, bhi = 1101
2025-07-02 06:41:16.892
2025-07-02 06:41:16.892     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.892         g = []
2025-07-02 06:41:16.893         if alo < ahi:
2025-07-02 06:41:16.893             if blo < bhi:
2025-07-02 06:41:16.893                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.893             else:
2025-07-02 06:41:16.893                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.893         elif blo < bhi:
2025-07-02 06:41:16.893             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.893
2025-07-02 06:41:16.893 >       yield from g
2025-07-02 06:41:16.893
2025-07-02 06:41:16.893 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.893 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.893
2025-07-02 06:41:16.893 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.893 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.893 alo = 136, ahi = 1101
2025-07-02 06:41:16.893 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.893 blo = 136, bhi = 1101
2025-07-02 06:41:16.894
2025-07-02 06:41:16.894     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.894         r"""
2025-07-02 06:41:16.894         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.894         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.894         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.894         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.894
2025-07-02 06:41:16.894         Example:
2025-07-02 06:41:16.894
2025-07-02 06:41:16.894         >>> d = Differ()
2025-07-02 06:41:16.894         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.894         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.894         >>> print(''.join(results), end="")
2025-07-02 06:41:16.894         - abcDefghiJkl
2025-07-02 06:41:16.894         + abcdefGhijkl
2025-07-02 06:41:16.894         """
2025-07-02 06:41:16.895
2025-07-02 06:41:16.895         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.895         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.895         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.895         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.895         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.895
2025-07-02 06:41:16.895         # search for the pair that matches best without being identical
2025-07-02 06:41:16.895         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.895         # on junk -- unless we have to)
2025-07-02 06:41:16.895         for j in range(blo, bhi):
2025-07-02 06:41:16.895             bj = b[j]
2025-07-02 06:41:16.895             cruncher.set_seq2(bj)
2025-07-02 06:41:16.895             for i in range(alo, ahi):
2025-07-02 06:41:16.895                 ai = a[i]
2025-07-02 06:41:16.895                 if ai == bj:
2025-07-02 06:41:16.895                     if eqi is None:
2025-07-02 06:41:16.896                         eqi, eqj = i, j
2025-07-02 06:41:16.896                     continue
2025-07-02 06:41:16.896                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.896                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.896                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.896                 # compares by a factor of 3.
2025-07-02 06:41:16.896                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.896                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.896                 # of the computation is cached by cruncher
2025-07-02 06:41:16.896                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.896                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.896                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.896                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.896         if best_ratio < cutoff:
2025-07-02 06:41:16.896             # no non-identical "pretty close" pair
2025-07-02 06:41:16.896             if eqi is None:
2025-07-02 06:41:16.896                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.896                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.896                 return
2025-07-02 06:41:16.897             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.897             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.897         else:
2025-07-02 06:41:16.897             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.897             eqi = None
2025-07-02 06:41:16.897
2025-07-02 06:41:16.897         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.897         # identical
2025-07-02 06:41:16.897
2025-07-02 06:41:16.897         # pump out diffs from before the synch point
2025-07-02 06:41:16.897         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.897
2025-07-02 06:41:16.897         # do intraline marking on the synch pair
2025-07-02 06:41:16.897         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.897         if eqi is None:
2025-07-02 06:41:16.897             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.897             atags = btags = ""
2025-07-02 06:41:16.897             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.898             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.898                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.898                 if tag == 'replace':
2025-07-02 06:41:16.898                     atags += '^' * la
2025-07-02 06:41:16.898                     btags += '^' * lb
2025-07-02 06:41:16.898                 elif tag == 'delete':
2025-07-02 06:41:16.898                     atags += '-' * la
2025-07-02 06:41:16.898                 elif tag == 'insert':
2025-07-02 06:41:16.898                     btags += '+' * lb
2025-07-02 06:41:16.898                 elif tag == 'equal':
2025-07-02 06:41:16.898                     atags += ' ' * la
2025-07-02 06:41:16.898                     btags += ' ' * lb
2025-07-02 06:41:16.898                 else:
2025-07-02 06:41:16.898                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.898             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.898         else:
2025-07-02 06:41:16.898             # the synch pair is identical
2025-07-02 06:41:16.898             yield '  ' + aelt
2025-07-02 06:41:16.898
2025-07-02 06:41:16.899         # pump out diffs from after the synch point
2025-07-02 06:41:16.899 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.899
2025-07-02 06:41:16.899 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.899 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.899
2025-07-02 06:41:16.899 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.899 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.899 alo = 137, ahi = 1101
2025-07-02 06:41:16.899 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.899 blo = 137, bhi = 1101
2025-07-02 06:41:16.899
2025-07-02 06:41:16.899     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.899         g = []
2025-07-02 06:41:16.899         if alo < ahi:
2025-07-02 06:41:16.899             if blo < bhi:
2025-07-02 06:41:16.899                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.900             else:
2025-07-02 06:41:16.900                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.900         elif blo < bhi:
2025-07-02 06:41:16.900             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.900
2025-07-02 06:41:16.900 >       yield from g
2025-07-02 06:41:16.900
2025-07-02 06:41:16.900 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.900 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.900
2025-07-02 06:41:16.900 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.900 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.900 alo = 137, ahi = 1101
2025-07-02 06:41:16.900 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.900 blo = 137, bhi = 1101
2025-07-02 06:41:16.900
2025-07-02 06:41:16.900     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.900         r"""
2025-07-02 06:41:16.900         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.901         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.901         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.901         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.901
2025-07-02 06:41:16.901         Example:
2025-07-02 06:41:16.901
2025-07-02 06:41:16.901         >>> d = Differ()
2025-07-02 06:41:16.901         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.901         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.901         >>> print(''.join(results), end="")
2025-07-02 06:41:16.901         - abcDefghiJkl
2025-07-02 06:41:16.901         + abcdefGhijkl
2025-07-02 06:41:16.901         """
2025-07-02 06:41:16.901
2025-07-02 06:41:16.901         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.901         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.902         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.902         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.902         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.902
2025-07-02 06:41:16.902         # search for the pair that matches best without being identical
2025-07-02 06:41:16.902         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.902         # on junk -- unless we have to)
2025-07-02 06:41:16.902         for j in range(blo, bhi):
2025-07-02 06:41:16.902             bj = b[j]
2025-07-02 06:41:16.902             cruncher.set_seq2(bj)
2025-07-02 06:41:16.902             for i in range(alo, ahi):
2025-07-02 06:41:16.902                 ai = a[i]
2025-07-02 06:41:16.902                 if ai == bj:
2025-07-02 06:41:16.902                     if eqi is None:
2025-07-02 06:41:16.902                         eqi, eqj = i, j
2025-07-02 06:41:16.902                     continue
2025-07-02 06:41:16.902                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.902                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.902                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.903                 # compares by a factor of 3.
2025-07-02 06:41:16.903                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.903                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.903                 # of the computation is cached by cruncher
2025-07-02 06:41:16.903                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.903                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.903                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.903                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.903         if best_ratio < cutoff:
2025-07-02 06:41:16.903             # no non-identical "pretty close" pair
2025-07-02 06:41:16.903             if eqi is None:
2025-07-02 06:41:16.903                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.903                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.903                 return
2025-07-02 06:41:16.903             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.903             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.903         else:
2025-07-02 06:41:16.904             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.904             eqi = None
2025-07-02 06:41:16.904
2025-07-02 06:41:16.904         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.904         # identical
2025-07-02 06:41:16.904
2025-07-02 06:41:16.904         # pump out diffs from before the synch point
2025-07-02 06:41:16.904         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.904
2025-07-02 06:41:16.904         # do intraline marking on the synch pair
2025-07-02 06:41:16.904         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.904         if eqi is None:
2025-07-02 06:41:16.904             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.904             atags = btags = ""
2025-07-02 06:41:16.904             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.904             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.904                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.904                 if tag == 'replace':
2025-07-02 06:41:16.905                     atags += '^' * la
2025-07-02 06:41:16.905                     btags += '^' * lb
2025-07-02 06:41:16.905                 elif tag == 'delete':
2025-07-02 06:41:16.905                     atags += '-' * la
2025-07-02 06:41:16.905                 elif tag == 'insert':
2025-07-02 06:41:16.905                     btags += '+' * lb
2025-07-02 06:41:16.905                 elif tag == 'equal':
2025-07-02 06:41:16.905                     atags += ' ' * la
2025-07-02 06:41:16.905                     btags += ' ' * lb
2025-07-02 06:41:16.905                 else:
2025-07-02 06:41:16.905                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.905             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.905         else:
2025-07-02 06:41:16.905             # the synch pair is identical
2025-07-02 06:41:16.905             yield '  ' + aelt
2025-07-02 06:41:16.905
2025-07-02 06:41:16.905         # pump out diffs from after the synch point
2025-07-02 06:41:16.905 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.906
2025-07-02 06:41:16.906 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.906 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.906
2025-07-02 06:41:16.906 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.906 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.906 alo = 138, ahi = 1101
2025-07-02 06:41:16.906 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.906 blo = 138, bhi = 1101
2025-07-02 06:41:16.906
2025-07-02 06:41:16.906     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.906         g = []
2025-07-02 06:41:16.906         if alo < ahi:
2025-07-02 06:41:16.906             if blo < bhi:
2025-07-02 06:41:16.906                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.906             else:
2025-07-02 06:41:16.906                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.906         elif blo < bhi:
2025-07-02 06:41:16.907             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.907
2025-07-02 06:41:16.907 >       yield from g
2025-07-02 06:41:16.907
2025-07-02 06:41:16.907 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.907 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.907
2025-07-02 06:41:16.907 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.907 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.907 alo = 138, ahi = 1101
2025-07-02 06:41:16.907 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.907 blo = 138, bhi = 1101
2025-07-02 06:41:16.907
2025-07-02 06:41:16.907     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.907         r"""
2025-07-02 06:41:16.907         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.907         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.907         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.908         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.908
2025-07-02 06:41:16.908         Example:
2025-07-02 06:41:16.908
2025-07-02 06:41:16.908         >>> d = Differ()
2025-07-02 06:41:16.908         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.908         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.908         >>> print(''.join(results), end="")
2025-07-02 06:41:16.908         - abcDefghiJkl
2025-07-02 06:41:16.908         + abcdefGhijkl
2025-07-02 06:41:16.908         """
2025-07-02 06:41:16.908
2025-07-02 06:41:16.908         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.908         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.908         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.908         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.908         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.909
2025-07-02 06:41:16.909         # search for the pair that matches best without being identical
2025-07-02 06:41:16.909         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.909         # on junk -- unless we have to)
2025-07-02 06:41:16.909         for j in range(blo, bhi):
2025-07-02 06:41:16.909             bj = b[j]
2025-07-02 06:41:16.909             cruncher.set_seq2(bj)
2025-07-02 06:41:16.909             for i in range(alo, ahi):
2025-07-02 06:41:16.909                 ai = a[i]
2025-07-02 06:41:16.909                 if ai == bj:
2025-07-02 06:41:16.909                     if eqi is None:
2025-07-02 06:41:16.909                         eqi, eqj = i, j
2025-07-02 06:41:16.909                     continue
2025-07-02 06:41:16.909                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.909                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.909                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.909                 # compares by a factor of 3.
2025-07-02 06:41:16.909                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.909                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.910                 # of the computation is cached by cruncher
2025-07-02 06:41:16.910                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.910                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.910                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.910                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.910         if best_ratio < cutoff:
2025-07-02 06:41:16.910             # no non-identical "pretty close" pair
2025-07-02 06:41:16.910             if eqi is None:
2025-07-02 06:41:16.910                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.910                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.910                 return
2025-07-02 06:41:16.910             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.910             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.910         else:
2025-07-02 06:41:16.910             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.910             eqi = None
2025-07-02 06:41:16.910
2025-07-02 06:41:16.910         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.911         # identical
2025-07-02 06:41:16.911
2025-07-02 06:41:16.911         # pump out diffs from before the synch point
2025-07-02 06:41:16.911         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.911
2025-07-02 06:41:16.911         # do intraline marking on the synch pair
2025-07-02 06:41:16.911         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.911         if eqi is None:
2025-07-02 06:41:16.911             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.911             atags = btags = ""
2025-07-02 06:41:16.911             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.911             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.911                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.911                 if tag == 'replace':
2025-07-02 06:41:16.911                     atags += '^' * la
2025-07-02 06:41:16.911                     btags += '^' * lb
2025-07-02 06:41:16.911                 elif tag == 'delete':
2025-07-02 06:41:16.911                     atags += '-' * la
2025-07-02 06:41:16.911                 elif tag == 'insert':
2025-07-02 06:41:16.912                     btags += '+' * lb
2025-07-02 06:41:16.912                 elif tag == 'equal':
2025-07-02 06:41:16.912                     atags += ' ' * la
2025-07-02 06:41:16.912                     btags += ' ' * lb
2025-07-02 06:41:16.912                 else:
2025-07-02 06:41:16.912                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.912             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.912         else:
2025-07-02 06:41:16.912             # the synch pair is identical
2025-07-02 06:41:16.912             yield '  ' + aelt
2025-07-02 06:41:16.912
2025-07-02 06:41:16.912         # pump out diffs from after the synch point
2025-07-02 06:41:16.912 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.912
2025-07-02 06:41:16.912 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.912 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.912
2025-07-02 06:41:16.912 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.912 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.913 alo = 139, ahi = 1101
2025-07-02 06:41:16.913 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.913 blo = 139, bhi = 1101
2025-07-02 06:41:16.913
2025-07-02 06:41:16.913     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.913         g = []
2025-07-02 06:41:16.913         if alo < ahi:
2025-07-02 06:41:16.913             if blo < bhi:
2025-07-02 06:41:16.913                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.913             else:
2025-07-02 06:41:16.913                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.913         elif blo < bhi:
2025-07-02 06:41:16.913             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.913
2025-07-02 06:41:16.913 >       yield from g
2025-07-02 06:41:16.913
2025-07-02 06:41:16.913 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.913 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.914
2025-07-02 06:41:16.914 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.914 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.914 alo = 139, ahi = 1101
2025-07-02 06:41:16.914 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.914 blo = 139, bhi = 1101
2025-07-02 06:41:16.914
2025-07-02 06:41:16.914     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.914         r"""
2025-07-02 06:41:16.914         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.914         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.914         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.914         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.914
2025-07-02 06:41:16.914         Example:
2025-07-02 06:41:16.914
2025-07-02 06:41:16.914         >>> d = Differ()
2025-07-02 06:41:16.914         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.915         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.915         >>> print(''.join(results), end="")
2025-07-02 06:41:16.915         - abcDefghiJkl
2025-07-02 06:41:16.915         + abcdefGhijkl
2025-07-02 06:41:16.915         """
2025-07-02 06:41:16.915
2025-07-02 06:41:16.915         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.915         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.915         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.915         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.915         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.915
2025-07-02 06:41:16.915         # search for the pair that matches best without being identical
2025-07-02 06:41:16.915         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.915         # on junk -- unless we have to)
2025-07-02 06:41:16.915         for j in range(blo, bhi):
2025-07-02 06:41:16.916             bj = b[j]
2025-07-02 06:41:16.916             cruncher.set_seq2(bj)
2025-07-02 06:41:16.916             for i in range(alo, ahi):
2025-07-02 06:41:16.916                 ai = a[i]
2025-07-02 06:41:16.916                 if ai == bj:
2025-07-02 06:41:16.916                     if eqi is None:
2025-07-02 06:41:16.916                         eqi, eqj = i, j
2025-07-02 06:41:16.916                     continue
2025-07-02 06:41:16.916                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.916                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.916                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.916                 # compares by a factor of 3.
2025-07-02 06:41:16.916                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.916                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.916                 # of the computation is cached by cruncher
2025-07-02 06:41:16.916                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.916                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.916                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.916                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.917         if best_ratio < cutoff:
2025-07-02 06:41:16.917             # no non-identical "pretty close" pair
2025-07-02 06:41:16.917             if eqi is None:
2025-07-02 06:41:16.917                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.917                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.917                 return
2025-07-02 06:41:16.917             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.917             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.917         else:
2025-07-02 06:41:16.917             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.917             eqi = None
2025-07-02 06:41:16.917
2025-07-02 06:41:16.917         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.917         # identical
2025-07-02 06:41:16.917
2025-07-02 06:41:16.917         # pump out diffs from before the synch point
2025-07-02 06:41:16.917         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.917
2025-07-02 06:41:16.917         # do intraline marking on the synch pair
2025-07-02 06:41:16.917         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.918         if eqi is None:
2025-07-02 06:41:16.918             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.918             atags = btags = ""
2025-07-02 06:41:16.918             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.918             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.918                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.918                 if tag == 'replace':
2025-07-02 06:41:16.918                     atags += '^' * la
2025-07-02 06:41:16.918                     btags += '^' * lb
2025-07-02 06:41:16.918                 elif tag == 'delete':
2025-07-02 06:41:16.918                     atags += '-' * la
2025-07-02 06:41:16.918                 elif tag == 'insert':
2025-07-02 06:41:16.918                     btags += '+' * lb
2025-07-02 06:41:16.918                 elif tag == 'equal':
2025-07-02 06:41:16.918                     atags += ' ' * la
2025-07-02 06:41:16.918                     btags += ' ' * lb
2025-07-02 06:41:16.918                 else:
2025-07-02 06:41:16.918                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.918             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.918         else:
2025-07-02 06:41:16.919             # the synch pair is identical
2025-07-02 06:41:16.919             yield '  ' + aelt
2025-07-02 06:41:16.919
2025-07-02 06:41:16.919         # pump out diffs from after the synch point
2025-07-02 06:41:16.919 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.919
2025-07-02 06:41:16.919 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.919 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.919
2025-07-02 06:41:16.919 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.919 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.919 alo = 140, ahi = 1101
2025-07-02 06:41:16.919 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.919 blo = 140, bhi = 1101
2025-07-02 06:41:16.919
2025-07-02 06:41:16.919     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.919         g = []
2025-07-02 06:41:16.919         if alo < ahi:
2025-07-02 06:41:16.920             if blo < bhi:
2025-07-02 06:41:16.920                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.920             else:
2025-07-02 06:41:16.920                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.920         elif blo < bhi:
2025-07-02 06:41:16.920             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.920
2025-07-02 06:41:16.920 >       yield from g
2025-07-02 06:41:16.920
2025-07-02 06:41:16.920 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.920 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.920
2025-07-02 06:41:16.920 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.920 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.920 alo = 140, ahi = 1101
2025-07-02 06:41:16.920 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.920 blo = 140, bhi = 1101
2025-07-02 06:41:16.920
2025-07-02 06:41:16.920     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.921         r"""
2025-07-02 06:41:16.921         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.921         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.921         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.921         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.921
2025-07-02 06:41:16.921         Example:
2025-07-02 06:41:16.921
2025-07-02 06:41:16.921         >>> d = Differ()
2025-07-02 06:41:16.921         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.921         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.921         >>> print(''.join(results), end="")
2025-07-02 06:41:16.921         - abcDefghiJkl
2025-07-02 06:41:16.921         + abcdefGhijkl
2025-07-02 06:41:16.921         """
2025-07-02 06:41:16.921
2025-07-02 06:41:16.921         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.922         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.922         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.922         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.922         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.922
2025-07-02 06:41:16.922         # search for the pair that matches best without being identical
2025-07-02 06:41:16.922         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.922         # on junk -- unless we have to)
2025-07-02 06:41:16.922         for j in range(blo, bhi):
2025-07-02 06:41:16.922             bj = b[j]
2025-07-02 06:41:16.922             cruncher.set_seq2(bj)
2025-07-02 06:41:16.922             for i in range(alo, ahi):
2025-07-02 06:41:16.922                 ai = a[i]
2025-07-02 06:41:16.922                 if ai == bj:
2025-07-02 06:41:16.922                     if eqi is None:
2025-07-02 06:41:16.922                         eqi, eqj = i, j
2025-07-02 06:41:16.922                     continue
2025-07-02 06:41:16.922                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.922                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.922                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.923                 # compares by a factor of 3.
2025-07-02 06:41:16.923                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.923                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.923                 # of the computation is cached by cruncher
2025-07-02 06:41:16.923                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.923                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.923                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.923                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.923         if best_ratio < cutoff:
2025-07-02 06:41:16.923             # no non-identical "pretty close" pair
2025-07-02 06:41:16.923             if eqi is None:
2025-07-02 06:41:16.923                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.923                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.923                 return
2025-07-02 06:41:16.923             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.923             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.923         else:
2025-07-02 06:41:16.924             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.924             eqi = None
2025-07-02 06:41:16.924
2025-07-02 06:41:16.924         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.924         # identical
2025-07-02 06:41:16.924
2025-07-02 06:41:16.924         # pump out diffs from before the synch point
2025-07-02 06:41:16.924         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.924
2025-07-02 06:41:16.924         # do intraline marking on the synch pair
2025-07-02 06:41:16.924         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.924         if eqi is None:
2025-07-02 06:41:16.924             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.924             atags = btags = ""
2025-07-02 06:41:16.924             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.924             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.924                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.924                 if tag == 'replace':
2025-07-02 06:41:16.924                     atags += '^' * la
2025-07-02 06:41:16.925                     btags += '^' * lb
2025-07-02 06:41:16.925                 elif tag == 'delete':
2025-07-02 06:41:16.925                     atags += '-' * la
2025-07-02 06:41:16.925                 elif tag == 'insert':
2025-07-02 06:41:16.925                     btags += '+' * lb
2025-07-02 06:41:16.925                 elif tag == 'equal':
2025-07-02 06:41:16.925                     atags += ' ' * la
2025-07-02 06:41:16.925                     btags += ' ' * lb
2025-07-02 06:41:16.925                 else:
2025-07-02 06:41:16.925                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.925             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.925         else:
2025-07-02 06:41:16.925             # the synch pair is identical
2025-07-02 06:41:16.925             yield '  ' + aelt
2025-07-02 06:41:16.925
2025-07-02 06:41:16.925         # pump out diffs from after the synch point
2025-07-02 06:41:16.925 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.925
2025-07-02 06:41:16.925 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.926 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.926
2025-07-02 06:41:16.926 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.926 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.926 alo = 141, ahi = 1101
2025-07-02 06:41:16.926 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.926 blo = 141, bhi = 1101
2025-07-02 06:41:16.926
2025-07-02 06:41:16.926     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.926         g = []
2025-07-02 06:41:16.926         if alo < ahi:
2025-07-02 06:41:16.926             if blo < bhi:
2025-07-02 06:41:16.926                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.926             else:
2025-07-02 06:41:16.926                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.926         elif blo < bhi:
2025-07-02 06:41:16.926             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.926
2025-07-02 06:41:16.926 >       yield from g
2025-07-02 06:41:16.926
2025-07-02 06:41:16.927 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.927 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.927
2025-07-02 06:41:16.927 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.927 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.927 alo = 141, ahi = 1101
2025-07-02 06:41:16.927 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.927 blo = 141, bhi = 1101
2025-07-02 06:41:16.927
2025-07-02 06:41:16.927     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.927         r"""
2025-07-02 06:41:16.927         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.927         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.927         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.927         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.927
2025-07-02 06:41:16.927         Example:
2025-07-02 06:41:16.927
2025-07-02 06:41:16.927         >>> d = Differ()
2025-07-02 06:41:16.928         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.928         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.928         >>> print(''.join(results), end="")
2025-07-02 06:41:16.928         - abcDefghiJkl
2025-07-02 06:41:16.928         + abcdefGhijkl
2025-07-02 06:41:16.928         """
2025-07-02 06:41:16.928
2025-07-02 06:41:16.928         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.928         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.928         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.928         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.928         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.928
2025-07-02 06:41:16.928         # search for the pair that matches best without being identical
2025-07-02 06:41:16.928         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.928         # on junk -- unless we have to)
2025-07-02 06:41:16.928         for j in range(blo, bhi):
2025-07-02 06:41:16.929             bj = b[j]
2025-07-02 06:41:16.929             cruncher.set_seq2(bj)
2025-07-02 06:41:16.929             for i in range(alo, ahi):
2025-07-02 06:41:16.929                 ai = a[i]
2025-07-02 06:41:16.929                 if ai == bj:
2025-07-02 06:41:16.929                     if eqi is None:
2025-07-02 06:41:16.929                         eqi, eqj = i, j
2025-07-02 06:41:16.929                     continue
2025-07-02 06:41:16.929                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.929                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.929                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.929                 # compares by a factor of 3.
2025-07-02 06:41:16.929                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.929                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.929                 # of the computation is cached by cruncher
2025-07-02 06:41:16.929                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.929                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.929                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.929                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.929         if best_ratio < cutoff:
2025-07-02 06:41:16.930             # no non-identical "pretty close" pair
2025-07-02 06:41:16.930             if eqi is None:
2025-07-02 06:41:16.930                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.930                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.930                 return
2025-07-02 06:41:16.930             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.930             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.930         else:
2025-07-02 06:41:16.930             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.930             eqi = None
2025-07-02 06:41:16.930
2025-07-02 06:41:16.930         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.930         # identical
2025-07-02 06:41:16.930
2025-07-02 06:41:16.930         # pump out diffs from before the synch point
2025-07-02 06:41:16.930         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.930
2025-07-02 06:41:16.930         # do intraline marking on the synch pair
2025-07-02 06:41:16.930         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.931         if eqi is None:
2025-07-02 06:41:16.931             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.931             atags = btags = ""
2025-07-02 06:41:16.931             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.931             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.931                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.931                 if tag == 'replace':
2025-07-02 06:41:16.931                     atags += '^' * la
2025-07-02 06:41:16.931                     btags += '^' * lb
2025-07-02 06:41:16.931                 elif tag == 'delete':
2025-07-02 06:41:16.931                     atags += '-' * la
2025-07-02 06:41:16.931                 elif tag == 'insert':
2025-07-02 06:41:16.931                     btags += '+' * lb
2025-07-02 06:41:16.931                 elif tag == 'equal':
2025-07-02 06:41:16.931                     atags += ' ' * la
2025-07-02 06:41:16.931                     btags += ' ' * lb
2025-07-02 06:41:16.931                 else:
2025-07-02 06:41:16.931                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.931             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.931         else:
2025-07-02 06:41:16.932             # the synch pair is identical
2025-07-02 06:41:16.932             yield '  ' + aelt
2025-07-02 06:41:16.932
2025-07-02 06:41:16.932         # pump out diffs from after the synch point
2025-07-02 06:41:16.932 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.932
2025-07-02 06:41:16.932 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.932 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.932
2025-07-02 06:41:16.932 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.932 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.932 alo = 142, ahi = 1101
2025-07-02 06:41:16.932 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.932 blo = 142, bhi = 1101
2025-07-02 06:41:16.932
2025-07-02 06:41:16.932     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.932         g = []
2025-07-02 06:41:16.932         if alo < ahi:
2025-07-02 06:41:16.933             if blo < bhi:
2025-07-02 06:41:16.933                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.933             else:
2025-07-02 06:41:16.933                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.933         elif blo < bhi:
2025-07-02 06:41:16.933             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.933
2025-07-02 06:41:16.933 >       yield from g
2025-07-02 06:41:16.933
2025-07-02 06:41:16.933 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.933 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.933
2025-07-02 06:41:16.933 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.933 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.933 alo = 142, ahi = 1101
2025-07-02 06:41:16.933 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.933 blo = 142, bhi = 1101
2025-07-02 06:41:16.933
2025-07-02 06:41:16.933     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.934         r"""
2025-07-02 06:41:16.934         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.934         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.934         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.934         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.934
2025-07-02 06:41:16.934         Example:
2025-07-02 06:41:16.934
2025-07-02 06:41:16.934         >>> d = Differ()
2025-07-02 06:41:16.934         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.934         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.934         >>> print(''.join(results), end="")
2025-07-02 06:41:16.934         - abcDefghiJkl
2025-07-02 06:41:16.934         + abcdefGhijkl
2025-07-02 06:41:16.934         """
2025-07-02 06:41:16.934
2025-07-02 06:41:16.934         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.935         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.935         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.935         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.935         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.935
2025-07-02 06:41:16.935         # search for the pair that matches best without being identical
2025-07-02 06:41:16.935         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.935         # on junk -- unless we have to)
2025-07-02 06:41:16.935         for j in range(blo, bhi):
2025-07-02 06:41:16.935             bj = b[j]
2025-07-02 06:41:16.935             cruncher.set_seq2(bj)
2025-07-02 06:41:16.935             for i in range(alo, ahi):
2025-07-02 06:41:16.935                 ai = a[i]
2025-07-02 06:41:16.935                 if ai == bj:
2025-07-02 06:41:16.935                     if eqi is None:
2025-07-02 06:41:16.935                         eqi, eqj = i, j
2025-07-02 06:41:16.935                     continue
2025-07-02 06:41:16.936                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.936                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.936                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.936                 # compares by a factor of 3.
2025-07-02 06:41:16.936                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.936                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.936                 # of the computation is cached by cruncher
2025-07-02 06:41:16.936                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.936                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.936                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.936                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.936         if best_ratio < cutoff:
2025-07-02 06:41:16.936             # no non-identical "pretty close" pair
2025-07-02 06:41:16.936             if eqi is None:
2025-07-02 06:41:16.936                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.936                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.936                 return
2025-07-02 06:41:16.936             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.936             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.937         else:
2025-07-02 06:41:16.937             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.937             eqi = None
2025-07-02 06:41:16.937
2025-07-02 06:41:16.937         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.937         # identical
2025-07-02 06:41:16.937
2025-07-02 06:41:16.937         # pump out diffs from before the synch point
2025-07-02 06:41:16.937         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.937
2025-07-02 06:41:16.937         # do intraline marking on the synch pair
2025-07-02 06:41:16.937         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.937         if eqi is None:
2025-07-02 06:41:16.937             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.937             atags = btags = ""
2025-07-02 06:41:16.937             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.937             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.937                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.937                 if tag == 'replace':
2025-07-02 06:41:16.938                     atags += '^' * la
2025-07-02 06:41:16.938                     btags += '^' * lb
2025-07-02 06:41:16.938                 elif tag == 'delete':
2025-07-02 06:41:16.938                     atags += '-' * la
2025-07-02 06:41:16.938                 elif tag == 'insert':
2025-07-02 06:41:16.938                     btags += '+' * lb
2025-07-02 06:41:16.938                 elif tag == 'equal':
2025-07-02 06:41:16.938                     atags += ' ' * la
2025-07-02 06:41:16.938                     btags += ' ' * lb
2025-07-02 06:41:16.938                 else:
2025-07-02 06:41:16.938                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.938             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.938         else:
2025-07-02 06:41:16.938             # the synch pair is identical
2025-07-02 06:41:16.938             yield '  ' + aelt
2025-07-02 06:41:16.938
2025-07-02 06:41:16.938         # pump out diffs from after the synch point
2025-07-02 06:41:16.938 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.938
2025-07-02 06:41:16.939 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.939 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.939
2025-07-02 06:41:16.939 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.939 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.939 alo = 143, ahi = 1101
2025-07-02 06:41:16.939 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.939 blo = 143, bhi = 1101
2025-07-02 06:41:16.939
2025-07-02 06:41:16.939     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.939         g = []
2025-07-02 06:41:16.939         if alo < ahi:
2025-07-02 06:41:16.939             if blo < bhi:
2025-07-02 06:41:16.939                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.939             else:
2025-07-02 06:41:16.939                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.939         elif blo < bhi:
2025-07-02 06:41:16.939             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.939
2025-07-02 06:41:16.940 >       yield from g
2025-07-02 06:41:16.940
2025-07-02 06:41:16.940 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.940 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.940
2025-07-02 06:41:16.940 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.940 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.940 alo = 143, ahi = 1101
2025-07-02 06:41:16.940 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.940 blo = 143, bhi = 1101
2025-07-02 06:41:16.940
2025-07-02 06:41:16.940     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.940         r"""
2025-07-02 06:41:16.940         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.940         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.940         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.940         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.940
2025-07-02 06:41:16.940         Example:
2025-07-02 06:41:16.940
2025-07-02 06:41:16.941         >>> d = Differ()
2025-07-02 06:41:16.941         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.941         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.941         >>> print(''.join(results), end="")
2025-07-02 06:41:16.941         - abcDefghiJkl
2025-07-02 06:41:16.941         + abcdefGhijkl
2025-07-02 06:41:16.941         """
2025-07-02 06:41:16.941
2025-07-02 06:41:16.941         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.941         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.941         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.941         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.941         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.941
2025-07-02 06:41:16.941         # search for the pair that matches best without being identical
2025-07-02 06:41:16.941         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.942         # on junk -- unless we have to)
2025-07-02 06:41:16.942         for j in range(blo, bhi):
2025-07-02 06:41:16.942             bj = b[j]
2025-07-02 06:41:16.942             cruncher.set_seq2(bj)
2025-07-02 06:41:16.942             for i in range(alo, ahi):
2025-07-02 06:41:16.942                 ai = a[i]
2025-07-02 06:41:16.942                 if ai == bj:
2025-07-02 06:41:16.942                     if eqi is None:
2025-07-02 06:41:16.942                         eqi, eqj = i, j
2025-07-02 06:41:16.942                     continue
2025-07-02 06:41:16.942                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.942                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.942                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.942                 # compares by a factor of 3.
2025-07-02 06:41:16.942                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.942                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.942                 # of the computation is cached by cruncher
2025-07-02 06:41:16.942                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.942                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.943                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.943                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.943         if best_ratio < cutoff:
2025-07-02 06:41:16.943             # no non-identical "pretty close" pair
2025-07-02 06:41:16.943             if eqi is None:
2025-07-02 06:41:16.943                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.943                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.943                 return
2025-07-02 06:41:16.943             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.943             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.943         else:
2025-07-02 06:41:16.943             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.943             eqi = None
2025-07-02 06:41:16.943
2025-07-02 06:41:16.943         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.943         # identical
2025-07-02 06:41:16.943
2025-07-02 06:41:16.943         # pump out diffs from before the synch point
2025-07-02 06:41:16.943         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.944
2025-07-02 06:41:16.944         # do intraline marking on the synch pair
2025-07-02 06:41:16.944         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.944         if eqi is None:
2025-07-02 06:41:16.944             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.944             atags = btags = ""
2025-07-02 06:41:16.944             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.944             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.944                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.944                 if tag == 'replace':
2025-07-02 06:41:16.944                     atags += '^' * la
2025-07-02 06:41:16.944                     btags += '^' * lb
2025-07-02 06:41:16.944                 elif tag == 'delete':
2025-07-02 06:41:16.944                     atags += '-' * la
2025-07-02 06:41:16.944                 elif tag == 'insert':
2025-07-02 06:41:16.944                     btags += '+' * lb
2025-07-02 06:41:16.944                 elif tag == 'equal':
2025-07-02 06:41:16.944                     atags += ' ' * la
2025-07-02 06:41:16.944                     btags += ' ' * lb
2025-07-02 06:41:16.944                 else:
2025-07-02 06:41:16.945                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.945             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.945         else:
2025-07-02 06:41:16.945             # the synch pair is identical
2025-07-02 06:41:16.945             yield '  ' + aelt
2025-07-02 06:41:16.945
2025-07-02 06:41:16.945         # pump out diffs from after the synch point
2025-07-02 06:41:16.945 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.945
2025-07-02 06:41:16.945 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.945 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.945
2025-07-02 06:41:16.945 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.945 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.945 alo = 144, ahi = 1101
2025-07-02 06:41:16.945 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.945 blo = 144, bhi = 1101
2025-07-02 06:41:16.945
2025-07-02 06:41:16.945     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.946         g = []
2025-07-02 06:41:16.946         if alo < ahi:
2025-07-02 06:41:16.946             if blo < bhi:
2025-07-02 06:41:16.946                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.946             else:
2025-07-02 06:41:16.946                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.946         elif blo < bhi:
2025-07-02 06:41:16.946             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.946
2025-07-02 06:41:16.946 >       yield from g
2025-07-02 06:41:16.946
2025-07-02 06:41:16.946 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.946 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.946
2025-07-02 06:41:16.946 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.946 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.946 alo = 144, ahi = 1101
2025-07-02 06:41:16.946 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.946 blo = 144, bhi = 1101
2025-07-02 06:41:16.947
2025-07-02 06:41:16.947     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.947         r"""
2025-07-02 06:41:16.947         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.947         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.947         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.947         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.947
2025-07-02 06:41:16.947         Example:
2025-07-02 06:41:16.947
2025-07-02 06:41:16.947         >>> d = Differ()
2025-07-02 06:41:16.947         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.947         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.947         >>> print(''.join(results), end="")
2025-07-02 06:41:16.947         - abcDefghiJkl
2025-07-02 06:41:16.947         + abcdefGhijkl
2025-07-02 06:41:16.947         """
2025-07-02 06:41:16.947
2025-07-02 06:41:16.948         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.948         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.948         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.948         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.948         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.948
2025-07-02 06:41:16.948         # search for the pair that matches best without being identical
2025-07-02 06:41:16.948         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.948         # on junk -- unless we have to)
2025-07-02 06:41:16.948         for j in range(blo, bhi):
2025-07-02 06:41:16.948             bj = b[j]
2025-07-02 06:41:16.948             cruncher.set_seq2(bj)
2025-07-02 06:41:16.948             for i in range(alo, ahi):
2025-07-02 06:41:16.948                 ai = a[i]
2025-07-02 06:41:16.948                 if ai == bj:
2025-07-02 06:41:16.948                     if eqi is None:
2025-07-02 06:41:16.948                         eqi, eqj = i, j
2025-07-02 06:41:16.948                     continue
2025-07-02 06:41:16.948                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.949                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.949                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.949                 # compares by a factor of 3.
2025-07-02 06:41:16.949                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.949                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.949                 # of the computation is cached by cruncher
2025-07-02 06:41:16.949                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.949                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.949                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.949                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.949         if best_ratio < cutoff:
2025-07-02 06:41:16.949             # no non-identical "pretty close" pair
2025-07-02 06:41:16.949             if eqi is None:
2025-07-02 06:41:16.949                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.949                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.949                 return
2025-07-02 06:41:16.949             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.949             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.949         else:
2025-07-02 06:41:16.950             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.950             eqi = None
2025-07-02 06:41:16.950
2025-07-02 06:41:16.950         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.950         # identical
2025-07-02 06:41:16.950
2025-07-02 06:41:16.950         # pump out diffs from before the synch point
2025-07-02 06:41:16.950         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.950
2025-07-02 06:41:16.950         # do intraline marking on the synch pair
2025-07-02 06:41:16.950         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.950         if eqi is None:
2025-07-02 06:41:16.950             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.950             atags = btags = ""
2025-07-02 06:41:16.950             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.950             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.950                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.950                 if tag == 'replace':
2025-07-02 06:41:16.950                     atags += '^' * la
2025-07-02 06:41:16.951                     btags += '^' * lb
2025-07-02 06:41:16.951                 elif tag == 'delete':
2025-07-02 06:41:16.951                     atags += '-' * la
2025-07-02 06:41:16.951                 elif tag == 'insert':
2025-07-02 06:41:16.951                     btags += '+' * lb
2025-07-02 06:41:16.951                 elif tag == 'equal':
2025-07-02 06:41:16.951                     atags += ' ' * la
2025-07-02 06:41:16.951                     btags += ' ' * lb
2025-07-02 06:41:16.951                 else:
2025-07-02 06:41:16.951                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.951             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.951         else:
2025-07-02 06:41:16.951             # the synch pair is identical
2025-07-02 06:41:16.951             yield '  ' + aelt
2025-07-02 06:41:16.951
2025-07-02 06:41:16.951         # pump out diffs from after the synch point
2025-07-02 06:41:16.951 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.951
2025-07-02 06:41:16.952 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.952 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.952
2025-07-02 06:41:16.952 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.952 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.952 alo = 145, ahi = 1101
2025-07-02 06:41:16.952 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.952 blo = 145, bhi = 1101
2025-07-02 06:41:16.952
2025-07-02 06:41:16.952     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.952         g = []
2025-07-02 06:41:16.952         if alo < ahi:
2025-07-02 06:41:16.952             if blo < bhi:
2025-07-02 06:41:16.952                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.952             else:
2025-07-02 06:41:16.952                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.952         elif blo < bhi:
2025-07-02 06:41:16.952             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.953
2025-07-02 06:41:16.953 >       yield from g
2025-07-02 06:41:16.953
2025-07-02 06:41:16.953 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.953 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.953
2025-07-02 06:41:16.953 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.953 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.953 alo = 145, ahi = 1101
2025-07-02 06:41:16.953 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.953 blo = 145, bhi = 1101
2025-07-02 06:41:16.953
2025-07-02 06:41:16.953     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.953         r"""
2025-07-02 06:41:16.953         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.953         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.953         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.953         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.953
2025-07-02 06:41:16.954         Example:
2025-07-02 06:41:16.954
2025-07-02 06:41:16.954         >>> d = Differ()
2025-07-02 06:41:16.954         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.954         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.954         >>> print(''.join(results), end="")
2025-07-02 06:41:16.954         - abcDefghiJkl
2025-07-02 06:41:16.954         + abcdefGhijkl
2025-07-02 06:41:16.954         """
2025-07-02 06:41:16.954
2025-07-02 06:41:16.954         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.954         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.954         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.954         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.954         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.954
2025-07-02 06:41:16.954         # search for the pair that matches best without being identical
2025-07-02 06:41:16.955         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.955         # on junk -- unless we have to)
2025-07-02 06:41:16.955         for j in range(blo, bhi):
2025-07-02 06:41:16.955             bj = b[j]
2025-07-02 06:41:16.955             cruncher.set_seq2(bj)
2025-07-02 06:41:16.955             for i in range(alo, ahi):
2025-07-02 06:41:16.955                 ai = a[i]
2025-07-02 06:41:16.955                 if ai == bj:
2025-07-02 06:41:16.955                     if eqi is None:
2025-07-02 06:41:16.955                         eqi, eqj = i, j
2025-07-02 06:41:16.955                     continue
2025-07-02 06:41:16.955                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.955                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.955                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.955                 # compares by a factor of 3.
2025-07-02 06:41:16.955                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.955                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.955                 # of the computation is cached by cruncher
2025-07-02 06:41:16.955                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.956                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.956                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.956                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.956         if best_ratio < cutoff:
2025-07-02 06:41:16.956             # no non-identical "pretty close" pair
2025-07-02 06:41:16.956             if eqi is None:
2025-07-02 06:41:16.956                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.956                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.956                 return
2025-07-02 06:41:16.956             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.956             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.956         else:
2025-07-02 06:41:16.956             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.956             eqi = None
2025-07-02 06:41:16.956
2025-07-02 06:41:16.956         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.956         # identical
2025-07-02 06:41:16.956
2025-07-02 06:41:16.957         # pump out diffs from before the synch point
2025-07-02 06:41:16.957         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.957
2025-07-02 06:41:16.957         # do intraline marking on the synch pair
2025-07-02 06:41:16.957         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.957         if eqi is None:
2025-07-02 06:41:16.957             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.957             atags = btags = ""
2025-07-02 06:41:16.957             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.957             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.957                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.957                 if tag == 'replace':
2025-07-02 06:41:16.957                     atags += '^' * la
2025-07-02 06:41:16.957                     btags += '^' * lb
2025-07-02 06:41:16.957                 elif tag == 'delete':
2025-07-02 06:41:16.957                     atags += '-' * la
2025-07-02 06:41:16.957                 elif tag == 'insert':
2025-07-02 06:41:16.957                     btags += '+' * lb
2025-07-02 06:41:16.957                 elif tag == 'equal':
2025-07-02 06:41:16.958                     atags += ' ' * la
2025-07-02 06:41:16.958                     btags += ' ' * lb
2025-07-02 06:41:16.958                 else:
2025-07-02 06:41:16.958                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.958             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.958         else:
2025-07-02 06:41:16.958             # the synch pair is identical
2025-07-02 06:41:16.958             yield '  ' + aelt
2025-07-02 06:41:16.958
2025-07-02 06:41:16.958         # pump out diffs from after the synch point
2025-07-02 06:41:16.958 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.958
2025-07-02 06:41:16.958 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.958 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.958
2025-07-02 06:41:16.958 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.958 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.958 alo = 146, ahi = 1101
2025-07-02 06:41:16.958 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.959 blo = 146, bhi = 1101
2025-07-02 06:41:16.959
2025-07-02 06:41:16.959     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.959         g = []
2025-07-02 06:41:16.959         if alo < ahi:
2025-07-02 06:41:16.959             if blo < bhi:
2025-07-02 06:41:16.959                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.959             else:
2025-07-02 06:41:16.959                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.959         elif blo < bhi:
2025-07-02 06:41:16.959             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.959
2025-07-02 06:41:16.959 >       yield from g
2025-07-02 06:41:16.959
2025-07-02 06:41:16.959 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.959 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.959
2025-07-02 06:41:16.959 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.960 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.960 alo = 146, ahi = 1101
2025-07-02 06:41:16.960 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.960 blo = 146, bhi = 1101
2025-07-02 06:41:16.960
2025-07-02 06:41:16.960     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.960         r"""
2025-07-02 06:41:16.960         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.960         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.960         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.960         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.960
2025-07-02 06:41:16.960         Example:
2025-07-02 06:41:16.960
2025-07-02 06:41:16.960         >>> d = Differ()
2025-07-02 06:41:16.960         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.960         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.961         >>> print(''.join(results), end="")
2025-07-02 06:41:16.961         - abcDefghiJkl
2025-07-02 06:41:16.961         + abcdefGhijkl
2025-07-02 06:41:16.961         """
2025-07-02 06:41:16.961
2025-07-02 06:41:16.961         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.961         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.961         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.961         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.961         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.961
2025-07-02 06:41:16.961         # search for the pair that matches best without being identical
2025-07-02 06:41:16.961         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.961         # on junk -- unless we have to)
2025-07-02 06:41:16.961         for j in range(blo, bhi):
2025-07-02 06:41:16.961             bj = b[j]
2025-07-02 06:41:16.961             cruncher.set_seq2(bj)
2025-07-02 06:41:16.961             for i in range(alo, ahi):
2025-07-02 06:41:16.962                 ai = a[i]
2025-07-02 06:41:16.962                 if ai == bj:
2025-07-02 06:41:16.962                     if eqi is None:
2025-07-02 06:41:16.962                         eqi, eqj = i, j
2025-07-02 06:41:16.962                     continue
2025-07-02 06:41:16.962                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.962                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.962                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.962                 # compares by a factor of 3.
2025-07-02 06:41:16.962                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.962                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.962                 # of the computation is cached by cruncher
2025-07-02 06:41:16.962                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.962                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.962                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.962                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.962         if best_ratio < cutoff:
2025-07-02 06:41:16.962             # no non-identical "pretty close" pair
2025-07-02 06:41:16.962             if eqi is None:
2025-07-02 06:41:16.962                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.963                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.963                 return
2025-07-02 06:41:16.963             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.963             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.963         else:
2025-07-02 06:41:16.963             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.963             eqi = None
2025-07-02 06:41:16.963
2025-07-02 06:41:16.963         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.963         # identical
2025-07-02 06:41:16.963
2025-07-02 06:41:16.963         # pump out diffs from before the synch point
2025-07-02 06:41:16.963         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.963
2025-07-02 06:41:16.963         # do intraline marking on the synch pair
2025-07-02 06:41:16.963         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.963         if eqi is None:
2025-07-02 06:41:16.963             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.963             atags = btags = ""
2025-07-02 06:41:16.963             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.963             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.964                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.964                 if tag == 'replace':
2025-07-02 06:41:16.964                     atags += '^' * la
2025-07-02 06:41:16.964                     btags += '^' * lb
2025-07-02 06:41:16.964                 elif tag == 'delete':
2025-07-02 06:41:16.964                     atags += '-' * la
2025-07-02 06:41:16.964                 elif tag == 'insert':
2025-07-02 06:41:16.964                     btags += '+' * lb
2025-07-02 06:41:16.964                 elif tag == 'equal':
2025-07-02 06:41:16.964                     atags += ' ' * la
2025-07-02 06:41:16.964                     btags += ' ' * lb
2025-07-02 06:41:16.964                 else:
2025-07-02 06:41:16.964                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.964             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.964         else:
2025-07-02 06:41:16.964             # the synch pair is identical
2025-07-02 06:41:16.964             yield '  ' + aelt
2025-07-02 06:41:16.964
2025-07-02 06:41:16.964         # pump out diffs from after the synch point
2025-07-02 06:41:16.964 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.965
2025-07-02 06:41:16.965 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.965 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.965
2025-07-02 06:41:16.965 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.965 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.965 alo = 147, ahi = 1101
2025-07-02 06:41:16.965 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.965 blo = 147, bhi = 1101
2025-07-02 06:41:16.965
2025-07-02 06:41:16.965     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.965         g = []
2025-07-02 06:41:16.965         if alo < ahi:
2025-07-02 06:41:16.965             if blo < bhi:
2025-07-02 06:41:16.965                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.965             else:
2025-07-02 06:41:16.965                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.965         elif blo < bhi:
2025-07-02 06:41:16.965             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.965
2025-07-02 06:41:16.966 >       yield from g
2025-07-02 06:41:16.966
2025-07-02 06:41:16.966 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.966 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.966
2025-07-02 06:41:16.966 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.966 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.966 alo = 147, ahi = 1101
2025-07-02 06:41:16.966 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.966 blo = 147, bhi = 1101
2025-07-02 06:41:16.966
2025-07-02 06:41:16.966     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.966         r"""
2025-07-02 06:41:16.966         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.966         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.966         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.966         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.966
2025-07-02 06:41:16.967         Example:
2025-07-02 06:41:16.967
2025-07-02 06:41:16.967         >>> d = Differ()
2025-07-02 06:41:16.967         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.967         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.967         >>> print(''.join(results), end="")
2025-07-02 06:41:16.967         - abcDefghiJkl
2025-07-02 06:41:16.967         + abcdefGhijkl
2025-07-02 06:41:16.967         """
2025-07-02 06:41:16.967
2025-07-02 06:41:16.967         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.967         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.967         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.967         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.967         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.967
2025-07-02 06:41:16.967         # search for the pair that matches best without being identical
2025-07-02 06:41:16.967         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.967         # on junk -- unless we have to)
2025-07-02 06:41:16.968         for j in range(blo, bhi):
2025-07-02 06:41:16.968             bj = b[j]
2025-07-02 06:41:16.968             cruncher.set_seq2(bj)
2025-07-02 06:41:16.968             for i in range(alo, ahi):
2025-07-02 06:41:16.968                 ai = a[i]
2025-07-02 06:41:16.968                 if ai == bj:
2025-07-02 06:41:16.968                     if eqi is None:
2025-07-02 06:41:16.968                         eqi, eqj = i, j
2025-07-02 06:41:16.968                     continue
2025-07-02 06:41:16.968                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.968                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.968                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.968                 # compares by a factor of 3.
2025-07-02 06:41:16.968                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.968                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.968                 # of the computation is cached by cruncher
2025-07-02 06:41:16.968                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.968                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.968                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.969                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.969         if best_ratio < cutoff:
2025-07-02 06:41:16.969             # no non-identical "pretty close" pair
2025-07-02 06:41:16.969             if eqi is None:
2025-07-02 06:41:16.969                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.969                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.969                 return
2025-07-02 06:41:16.969             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.969             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.969         else:
2025-07-02 06:41:16.969             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.969             eqi = None
2025-07-02 06:41:16.969
2025-07-02 06:41:16.969         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.969         # identical
2025-07-02 06:41:16.969
2025-07-02 06:41:16.969         # pump out diffs from before the synch point
2025-07-02 06:41:16.969         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.969
2025-07-02 06:41:16.969         # do intraline marking on the synch pair
2025-07-02 06:41:16.970         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.970         if eqi is None:
2025-07-02 06:41:16.970             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.970             atags = btags = ""
2025-07-02 06:41:16.970             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.970             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.970                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.970                 if tag == 'replace':
2025-07-02 06:41:16.970                     atags += '^' * la
2025-07-02 06:41:16.970                     btags += '^' * lb
2025-07-02 06:41:16.970                 elif tag == 'delete':
2025-07-02 06:41:16.970                     atags += '-' * la
2025-07-02 06:41:16.970                 elif tag == 'insert':
2025-07-02 06:41:16.970                     btags += '+' * lb
2025-07-02 06:41:16.970                 elif tag == 'equal':
2025-07-02 06:41:16.970                     atags += ' ' * la
2025-07-02 06:41:16.970                     btags += ' ' * lb
2025-07-02 06:41:16.970                 else:
2025-07-02 06:41:16.970                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.970             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.971         else:
2025-07-02 06:41:16.971             # the synch pair is identical
2025-07-02 06:41:16.971             yield '  ' + aelt
2025-07-02 06:41:16.971
2025-07-02 06:41:16.971         # pump out diffs from after the synch point
2025-07-02 06:41:16.971 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.971
2025-07-02 06:41:16.971 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.971 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.971
2025-07-02 06:41:16.971 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.971 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.971 alo = 148, ahi = 1101
2025-07-02 06:41:16.971 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.971 blo = 148, bhi = 1101
2025-07-02 06:41:16.971
2025-07-02 06:41:16.971     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.971         g = []
2025-07-02 06:41:16.971         if alo < ahi:
2025-07-02 06:41:16.971             if blo < bhi:
2025-07-02 06:41:16.972                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.972             else:
2025-07-02 06:41:16.972                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.972         elif blo < bhi:
2025-07-02 06:41:16.972             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.972
2025-07-02 06:41:16.972 >       yield from g
2025-07-02 06:41:16.972
2025-07-02 06:41:16.972 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.972 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.972
2025-07-02 06:41:16.972 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.972 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.972 alo = 148, ahi = 1101
2025-07-02 06:41:16.972 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.972 blo = 148, bhi = 1101
2025-07-02 06:41:16.972
2025-07-02 06:41:16.972     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.972         r"""
2025-07-02 06:41:16.972         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.973         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.973         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.973         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.973
2025-07-02 06:41:16.973         Example:
2025-07-02 06:41:16.973
2025-07-02 06:41:16.973         >>> d = Differ()
2025-07-02 06:41:16.973         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.973         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.973         >>> print(''.join(results), end="")
2025-07-02 06:41:16.973         - abcDefghiJkl
2025-07-02 06:41:16.973         + abcdefGhijkl
2025-07-02 06:41:16.973         """
2025-07-02 06:41:16.973
2025-07-02 06:41:16.973         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.973         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.973         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.973         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.973         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.974
2025-07-02 06:41:16.974         # search for the pair that matches best without being identical
2025-07-02 06:41:16.974         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.974         # on junk -- unless we have to)
2025-07-02 06:41:16.974         for j in range(blo, bhi):
2025-07-02 06:41:16.974             bj = b[j]
2025-07-02 06:41:16.974             cruncher.set_seq2(bj)
2025-07-02 06:41:16.974             for i in range(alo, ahi):
2025-07-02 06:41:16.974                 ai = a[i]
2025-07-02 06:41:16.974                 if ai == bj:
2025-07-02 06:41:16.974                     if eqi is None:
2025-07-02 06:41:16.974                         eqi, eqj = i, j
2025-07-02 06:41:16.974                     continue
2025-07-02 06:41:16.974                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.974                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.974                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.974                 # compares by a factor of 3.
2025-07-02 06:41:16.974                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.974                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.974                 # of the computation is cached by cruncher
2025-07-02 06:41:16.975                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.975                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.975                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.975                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.975         if best_ratio < cutoff:
2025-07-02 06:41:16.975             # no non-identical "pretty close" pair
2025-07-02 06:41:16.975             if eqi is None:
2025-07-02 06:41:16.975                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.975                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.975                 return
2025-07-02 06:41:16.975             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.975             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.975         else:
2025-07-02 06:41:16.975             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.975             eqi = None
2025-07-02 06:41:16.975
2025-07-02 06:41:16.975         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.975         # identical
2025-07-02 06:41:16.975
2025-07-02 06:41:16.975         # pump out diffs from before the synch point
2025-07-02 06:41:16.975         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.976
2025-07-02 06:41:16.976         # do intraline marking on the synch pair
2025-07-02 06:41:16.976         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.976         if eqi is None:
2025-07-02 06:41:16.976             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.976             atags = btags = ""
2025-07-02 06:41:16.976             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.976             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.976                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.976                 if tag == 'replace':
2025-07-02 06:41:16.976                     atags += '^' * la
2025-07-02 06:41:16.976                     btags += '^' * lb
2025-07-02 06:41:16.976                 elif tag == 'delete':
2025-07-02 06:41:16.976                     atags += '-' * la
2025-07-02 06:41:16.976                 elif tag == 'insert':
2025-07-02 06:41:16.976                     btags += '+' * lb
2025-07-02 06:41:16.976                 elif tag == 'equal':
2025-07-02 06:41:16.976                     atags += ' ' * la
2025-07-02 06:41:16.976                     btags += ' ' * lb
2025-07-02 06:41:16.976                 else:
2025-07-02 06:41:16.977                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.977             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.977         else:
2025-07-02 06:41:16.977             # the synch pair is identical
2025-07-02 06:41:16.977             yield '  ' + aelt
2025-07-02 06:41:16.977
2025-07-02 06:41:16.977         # pump out diffs from after the synch point
2025-07-02 06:41:16.977 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.977
2025-07-02 06:41:16.977 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.977 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.977
2025-07-02 06:41:16.977 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.977 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.977 alo = 149, ahi = 1101
2025-07-02 06:41:16.977 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.977 blo = 149, bhi = 1101
2025-07-02 06:41:16.977
2025-07-02 06:41:16.977     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.978         g = []
2025-07-02 06:41:16.978         if alo < ahi:
2025-07-02 06:41:16.978             if blo < bhi:
2025-07-02 06:41:16.978                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.978             else:
2025-07-02 06:41:16.978                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.978         elif blo < bhi:
2025-07-02 06:41:16.978             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.978
2025-07-02 06:41:16.978 >       yield from g
2025-07-02 06:41:16.978
2025-07-02 06:41:16.978 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.978 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.978
2025-07-02 06:41:16.978 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.978 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.978 alo = 149, ahi = 1101
2025-07-02 06:41:16.978 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.978 blo = 149, bhi = 1101
2025-07-02 06:41:16.978
2025-07-02 06:41:16.979     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.979         r"""
2025-07-02 06:41:16.979         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.979         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.979         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.979         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.979
2025-07-02 06:41:16.979         Example:
2025-07-02 06:41:16.979
2025-07-02 06:41:16.979         >>> d = Differ()
2025-07-02 06:41:16.979         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.979         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.979         >>> print(''.join(results), end="")
2025-07-02 06:41:16.979         - abcDefghiJkl
2025-07-02 06:41:16.979         + abcdefGhijkl
2025-07-02 06:41:16.979         """
2025-07-02 06:41:16.979
2025-07-02 06:41:16.979         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.980         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.980         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.980         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.980         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.980
2025-07-02 06:41:16.980         # search for the pair that matches best without being identical
2025-07-02 06:41:16.980         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.980         # on junk -- unless we have to)
2025-07-02 06:41:16.980         for j in range(blo, bhi):
2025-07-02 06:41:16.980             bj = b[j]
2025-07-02 06:41:16.980             cruncher.set_seq2(bj)
2025-07-02 06:41:16.980             for i in range(alo, ahi):
2025-07-02 06:41:16.980                 ai = a[i]
2025-07-02 06:41:16.980                 if ai == bj:
2025-07-02 06:41:16.980                     if eqi is None:
2025-07-02 06:41:16.980                         eqi, eqj = i, j
2025-07-02 06:41:16.980                     continue
2025-07-02 06:41:16.980                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.980                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.980                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.980                 # compares by a factor of 3.
2025-07-02 06:41:16.981                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.981                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.981                 # of the computation is cached by cruncher
2025-07-02 06:41:16.981                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.981                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.981                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.981                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.981         if best_ratio < cutoff:
2025-07-02 06:41:16.981             # no non-identical "pretty close" pair
2025-07-02 06:41:16.981             if eqi is None:
2025-07-02 06:41:16.981                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.981                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.981                 return
2025-07-02 06:41:16.981             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.981             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.981         else:
2025-07-02 06:41:16.981             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.981             eqi = None
2025-07-02 06:41:16.981
2025-07-02 06:41:16.981         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.982         # identical
2025-07-02 06:41:16.982
2025-07-02 06:41:16.982         # pump out diffs from before the synch point
2025-07-02 06:41:16.982         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.982
2025-07-02 06:41:16.982         # do intraline marking on the synch pair
2025-07-02 06:41:16.982         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.982         if eqi is None:
2025-07-02 06:41:16.982             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.982             atags = btags = ""
2025-07-02 06:41:16.982             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.982             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.982                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.982                 if tag == 'replace':
2025-07-02 06:41:16.982                     atags += '^' * la
2025-07-02 06:41:16.982                     btags += '^' * lb
2025-07-02 06:41:16.982                 elif tag == 'delete':
2025-07-02 06:41:16.982                     atags += '-' * la
2025-07-02 06:41:16.983                 elif tag == 'insert':
2025-07-02 06:41:16.983                     btags += '+' * lb
2025-07-02 06:41:16.983                 elif tag == 'equal':
2025-07-02 06:41:16.983                     atags += ' ' * la
2025-07-02 06:41:16.983                     btags += ' ' * lb
2025-07-02 06:41:16.983                 else:
2025-07-02 06:41:16.983                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.983             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.983         else:
2025-07-02 06:41:16.983             # the synch pair is identical
2025-07-02 06:41:16.983             yield '  ' + aelt
2025-07-02 06:41:16.983
2025-07-02 06:41:16.983         # pump out diffs from after the synch point
2025-07-02 06:41:16.983 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.983
2025-07-02 06:41:16.983 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.983 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.983
2025-07-02 06:41:16.983 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.983 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.984 alo = 150, ahi = 1101
2025-07-02 06:41:16.984 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.984 blo = 150, bhi = 1101
2025-07-02 06:41:16.984
2025-07-02 06:41:16.984     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.984         g = []
2025-07-02 06:41:16.984         if alo < ahi:
2025-07-02 06:41:16.984             if blo < bhi:
2025-07-02 06:41:16.984                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.984             else:
2025-07-02 06:41:16.984                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.984         elif blo < bhi:
2025-07-02 06:41:16.984             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.984
2025-07-02 06:41:16.984 >       yield from g
2025-07-02 06:41:16.984
2025-07-02 06:41:16.984 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.984 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.985
2025-07-02 06:41:16.985 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.985 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.985 alo = 150, ahi = 1101
2025-07-02 06:41:16.985 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.985 blo = 150, bhi = 1101
2025-07-02 06:41:16.985
2025-07-02 06:41:16.985     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.985         r"""
2025-07-02 06:41:16.985         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.985         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.985         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.985         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.985
2025-07-02 06:41:16.985         Example:
2025-07-02 06:41:16.985
2025-07-02 06:41:16.985         >>> d = Differ()
2025-07-02 06:41:16.985         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.985         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.986         >>> print(''.join(results), end="")
2025-07-02 06:41:16.986         - abcDefghiJkl
2025-07-02 06:41:16.986         + abcdefGhijkl
2025-07-02 06:41:16.986         """
2025-07-02 06:41:16.986
2025-07-02 06:41:16.986         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.986         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.986         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.986         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.986         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.986
2025-07-02 06:41:16.986         # search for the pair that matches best without being identical
2025-07-02 06:41:16.986         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.986         # on junk -- unless we have to)
2025-07-02 06:41:16.986         for j in range(blo, bhi):
2025-07-02 06:41:16.986             bj = b[j]
2025-07-02 06:41:16.986             cruncher.set_seq2(bj)
2025-07-02 06:41:16.987             for i in range(alo, ahi):
2025-07-02 06:41:16.987                 ai = a[i]
2025-07-02 06:41:16.987                 if ai == bj:
2025-07-02 06:41:16.987                     if eqi is None:
2025-07-02 06:41:16.987                         eqi, eqj = i, j
2025-07-02 06:41:16.987                     continue
2025-07-02 06:41:16.987                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.987                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.987                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.987                 # compares by a factor of 3.
2025-07-02 06:41:16.987                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.987                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.987                 # of the computation is cached by cruncher
2025-07-02 06:41:16.987                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.987                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.987                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.987                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.987         if best_ratio < cutoff:
2025-07-02 06:41:16.987             # no non-identical "pretty close" pair
2025-07-02 06:41:16.987             if eqi is None:
2025-07-02 06:41:16.988                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.988                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.988                 return
2025-07-02 06:41:16.988             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.988             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.988         else:
2025-07-02 06:41:16.988             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.988             eqi = None
2025-07-02 06:41:16.988
2025-07-02 06:41:16.988         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.988         # identical
2025-07-02 06:41:16.988
2025-07-02 06:41:16.988         # pump out diffs from before the synch point
2025-07-02 06:41:16.988         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.988
2025-07-02 06:41:16.988         # do intraline marking on the synch pair
2025-07-02 06:41:16.988         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.988         if eqi is None:
2025-07-02 06:41:16.988             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.988             atags = btags = ""
2025-07-02 06:41:16.989             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.989             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.989                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.989                 if tag == 'replace':
2025-07-02 06:41:16.989                     atags += '^' * la
2025-07-02 06:41:16.989                     btags += '^' * lb
2025-07-02 06:41:16.989                 elif tag == 'delete':
2025-07-02 06:41:16.989                     atags += '-' * la
2025-07-02 06:41:16.989                 elif tag == 'insert':
2025-07-02 06:41:16.989                     btags += '+' * lb
2025-07-02 06:41:16.989                 elif tag == 'equal':
2025-07-02 06:41:16.989                     atags += ' ' * la
2025-07-02 06:41:16.989                     btags += ' ' * lb
2025-07-02 06:41:16.989                 else:
2025-07-02 06:41:16.989                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.989             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.989         else:
2025-07-02 06:41:16.989             # the synch pair is identical
2025-07-02 06:41:16.989             yield '  ' + aelt
2025-07-02 06:41:16.989
2025-07-02 06:41:16.989         # pump out diffs from after the synch point
2025-07-02 06:41:16.990 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.990
2025-07-02 06:41:16.990 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.990 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.990
2025-07-02 06:41:16.990 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.990 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.990 alo = 151, ahi = 1101
2025-07-02 06:41:16.990 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.990 blo = 151, bhi = 1101
2025-07-02 06:41:16.990
2025-07-02 06:41:16.990     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.990         g = []
2025-07-02 06:41:16.990         if alo < ahi:
2025-07-02 06:41:16.990             if blo < bhi:
2025-07-02 06:41:16.990                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.990             else:
2025-07-02 06:41:16.990                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.990         elif blo < bhi:
2025-07-02 06:41:16.990             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991 >       yield from g
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.991 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.991 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.991 alo = 151, ahi = 1101
2025-07-02 06:41:16.991 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.991 blo = 151, bhi = 1101
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.991         r"""
2025-07-02 06:41:16.991         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.991         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.991         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.991         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.991
2025-07-02 06:41:16.991         Example:
2025-07-02 06:41:16.992
2025-07-02 06:41:16.992         >>> d = Differ()
2025-07-02 06:41:16.992         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.992         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.992         >>> print(''.join(results), end="")
2025-07-02 06:41:16.992         - abcDefghiJkl
2025-07-02 06:41:16.992         + abcdefGhijkl
2025-07-02 06:41:16.992         """
2025-07-02 06:41:16.992
2025-07-02 06:41:16.992         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.992         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.992         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.992         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.992         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.992
2025-07-02 06:41:16.992         # search for the pair that matches best without being identical
2025-07-02 06:41:16.992         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.992         # on junk -- unless we have to)
2025-07-02 06:41:16.992         for j in range(blo, bhi):
2025-07-02 06:41:16.993             bj = b[j]
2025-07-02 06:41:16.993             cruncher.set_seq2(bj)
2025-07-02 06:41:16.993             for i in range(alo, ahi):
2025-07-02 06:41:16.993                 ai = a[i]
2025-07-02 06:41:16.993                 if ai == bj:
2025-07-02 06:41:16.993                     if eqi is None:
2025-07-02 06:41:16.993                         eqi, eqj = i, j
2025-07-02 06:41:16.993                     continue
2025-07-02 06:41:16.993                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.993                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.993                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.993                 # compares by a factor of 3.
2025-07-02 06:41:16.993                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:16.993                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:16.993                 # of the computation is cached by cruncher
2025-07-02 06:41:16.993                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:16.993                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:16.993                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:16.993                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:16.993         if best_ratio < cutoff:
2025-07-02 06:41:16.994             # no non-identical "pretty close" pair
2025-07-02 06:41:16.994             if eqi is None:
2025-07-02 06:41:16.994                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:16.994                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.994                 return
2025-07-02 06:41:16.994             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:16.994             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:16.994         else:
2025-07-02 06:41:16.994             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:16.994             eqi = None
2025-07-02 06:41:16.994
2025-07-02 06:41:16.994         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:16.994         # identical
2025-07-02 06:41:16.994
2025-07-02 06:41:16.994         # pump out diffs from before the synch point
2025-07-02 06:41:16.994         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:16.994
2025-07-02 06:41:16.994         # do intraline marking on the synch pair
2025-07-02 06:41:16.994         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:16.995         if eqi is None:
2025-07-02 06:41:16.995             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:16.995             atags = btags = ""
2025-07-02 06:41:16.995             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:16.995             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:16.995                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:16.995                 if tag == 'replace':
2025-07-02 06:41:16.995                     atags += '^' * la
2025-07-02 06:41:16.995                     btags += '^' * lb
2025-07-02 06:41:16.995                 elif tag == 'delete':
2025-07-02 06:41:16.995                     atags += '-' * la
2025-07-02 06:41:16.995                 elif tag == 'insert':
2025-07-02 06:41:16.995                     btags += '+' * lb
2025-07-02 06:41:16.995                 elif tag == 'equal':
2025-07-02 06:41:16.995                     atags += ' ' * la
2025-07-02 06:41:16.995                     btags += ' ' * lb
2025-07-02 06:41:16.995                 else:
2025-07-02 06:41:16.995                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:16.995             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:16.996         else:
2025-07-02 06:41:16.996             # the synch pair is identical
2025-07-02 06:41:16.996             yield '  ' + aelt
2025-07-02 06:41:16.996
2025-07-02 06:41:16.996         # pump out diffs from after the synch point
2025-07-02 06:41:16.996 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:16.996
2025-07-02 06:41:16.996 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:16.996 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.996
2025-07-02 06:41:16.996 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.996 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.996 alo = 152, ahi = 1101
2025-07-02 06:41:16.996 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.996 blo = 152, bhi = 1101
2025-07-02 06:41:16.996
2025-07-02 06:41:16.996     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.996         g = []
2025-07-02 06:41:16.996         if alo < ahi:
2025-07-02 06:41:16.996             if blo < bhi:
2025-07-02 06:41:16.997                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:16.997             else:
2025-07-02 06:41:16.997                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:16.997         elif blo < bhi:
2025-07-02 06:41:16.997             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:16.997
2025-07-02 06:41:16.997 >       yield from g
2025-07-02 06:41:16.997
2025-07-02 06:41:16.997 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:16.997 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:16.997
2025-07-02 06:41:16.997 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:16.997 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:16.997 alo = 152, ahi = 1101
2025-07-02 06:41:16.997 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:16.997 blo = 152, bhi = 1101
2025-07-02 06:41:16.997
2025-07-02 06:41:16.997     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:16.998         r"""
2025-07-02 06:41:16.998         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:16.998         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:16.998         synch point, and intraline difference marking is done on the
2025-07-02 06:41:16.998         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:16.998
2025-07-02 06:41:16.998         Example:
2025-07-02 06:41:16.998
2025-07-02 06:41:16.998         >>> d = Differ()
2025-07-02 06:41:16.998         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:16.998         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:16.998         >>> print(''.join(results), end="")
2025-07-02 06:41:16.998         - abcDefghiJkl
2025-07-02 06:41:16.998         + abcdefGhijkl
2025-07-02 06:41:16.998         """
2025-07-02 06:41:16.998
2025-07-02 06:41:16.998         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:16.998         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:16.999         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:16.999         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:16.999         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:16.999
2025-07-02 06:41:16.999         # search for the pair that matches best without being identical
2025-07-02 06:41:16.999         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:16.999         # on junk -- unless we have to)
2025-07-02 06:41:16.999         for j in range(blo, bhi):
2025-07-02 06:41:16.999             bj = b[j]
2025-07-02 06:41:16.999             cruncher.set_seq2(bj)
2025-07-02 06:41:16.999             for i in range(alo, ahi):
2025-07-02 06:41:16.999                 ai = a[i]
2025-07-02 06:41:16.999                 if ai == bj:
2025-07-02 06:41:16.999                     if eqi is None:
2025-07-02 06:41:16.999                         eqi, eqj = i, j
2025-07-02 06:41:16.999                     continue
2025-07-02 06:41:16.999                 cruncher.set_seq1(ai)
2025-07-02 06:41:16.999                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:16.999                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:16.999                 # compares by a factor of 3.
2025-07-02 06:41:17.000                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.000                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.000                 # of the computation is cached by cruncher
2025-07-02 06:41:17.000                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.000                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.000                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.000                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.000         if best_ratio < cutoff:
2025-07-02 06:41:17.000             # no non-identical "pretty close" pair
2025-07-02 06:41:17.000             if eqi is None:
2025-07-02 06:41:17.000                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.000                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.000                 return
2025-07-02 06:41:17.000             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.000             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.000         else:
2025-07-02 06:41:17.000             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.000             eqi = None
2025-07-02 06:41:17.000
2025-07-02 06:41:17.000         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.001         # identical
2025-07-02 06:41:17.001
2025-07-02 06:41:17.001         # pump out diffs from before the synch point
2025-07-02 06:41:17.001         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.001
2025-07-02 06:41:17.001         # do intraline marking on the synch pair
2025-07-02 06:41:17.001         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.001         if eqi is None:
2025-07-02 06:41:17.001             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.001             atags = btags = ""
2025-07-02 06:41:17.001             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.001             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.001                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.001                 if tag == 'replace':
2025-07-02 06:41:17.001                     atags += '^' * la
2025-07-02 06:41:17.001                     btags += '^' * lb
2025-07-02 06:41:17.001                 elif tag == 'delete':
2025-07-02 06:41:17.001                     atags += '-' * la
2025-07-02 06:41:17.001                 elif tag == 'insert':
2025-07-02 06:41:17.001                     btags += '+' * lb
2025-07-02 06:41:17.002                 elif tag == 'equal':
2025-07-02 06:41:17.002                     atags += ' ' * la
2025-07-02 06:41:17.002                     btags += ' ' * lb
2025-07-02 06:41:17.002                 else:
2025-07-02 06:41:17.002                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.002             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.002         else:
2025-07-02 06:41:17.002             # the synch pair is identical
2025-07-02 06:41:17.002             yield '  ' + aelt
2025-07-02 06:41:17.002
2025-07-02 06:41:17.002         # pump out diffs from after the synch point
2025-07-02 06:41:17.002 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.002
2025-07-02 06:41:17.002 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.002 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.002
2025-07-02 06:41:17.002 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.002 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.002 alo = 153, ahi = 1101
2025-07-02 06:41:17.002 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.003 blo = 153, bhi = 1101
2025-07-02 06:41:17.003
2025-07-02 06:41:17.003     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.003         g = []
2025-07-02 06:41:17.003         if alo < ahi:
2025-07-02 06:41:17.003             if blo < bhi:
2025-07-02 06:41:17.003                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.003             else:
2025-07-02 06:41:17.003                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.003         elif blo < bhi:
2025-07-02 06:41:17.003             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.003
2025-07-02 06:41:17.003 >       yield from g
2025-07-02 06:41:17.003
2025-07-02 06:41:17.003 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.003 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.003
2025-07-02 06:41:17.004 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.004 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.004 alo = 153, ahi = 1101
2025-07-02 06:41:17.004 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.004 blo = 153, bhi = 1101
2025-07-02 06:41:17.004
2025-07-02 06:41:17.004     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.004         r"""
2025-07-02 06:41:17.004         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.004         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.004         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.004         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.004
2025-07-02 06:41:17.004         Example:
2025-07-02 06:41:17.004
2025-07-02 06:41:17.004         >>> d = Differ()
2025-07-02 06:41:17.004         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.004         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.004         >>> print(''.join(results), end="")
2025-07-02 06:41:17.005         - abcDefghiJkl
2025-07-02 06:41:17.005         + abcdefGhijkl
2025-07-02 06:41:17.005         """
2025-07-02 06:41:17.005
2025-07-02 06:41:17.005         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.005         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.005         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.005         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.005         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.005
2025-07-02 06:41:17.005         # search for the pair that matches best without being identical
2025-07-02 06:41:17.005         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.005         # on junk -- unless we have to)
2025-07-02 06:41:17.005         for j in range(blo, bhi):
2025-07-02 06:41:17.005             bj = b[j]
2025-07-02 06:41:17.005             cruncher.set_seq2(bj)
2025-07-02 06:41:17.005             for i in range(alo, ahi):
2025-07-02 06:41:17.005                 ai = a[i]
2025-07-02 06:41:17.006                 if ai == bj:
2025-07-02 06:41:17.006                     if eqi is None:
2025-07-02 06:41:17.006                         eqi, eqj = i, j
2025-07-02 06:41:17.006                     continue
2025-07-02 06:41:17.006                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.006                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.006                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.006                 # compares by a factor of 3.
2025-07-02 06:41:17.006                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.006                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.006                 # of the computation is cached by cruncher
2025-07-02 06:41:17.006                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.006                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.006                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.006                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.006         if best_ratio < cutoff:
2025-07-02 06:41:17.006             # no non-identical "pretty close" pair
2025-07-02 06:41:17.006             if eqi is None:
2025-07-02 06:41:17.006                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.006                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.006                 return
2025-07-02 06:41:17.007             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.007             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.007         else:
2025-07-02 06:41:17.007             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.007             eqi = None
2025-07-02 06:41:17.007
2025-07-02 06:41:17.007         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.007         # identical
2025-07-02 06:41:17.007
2025-07-02 06:41:17.007         # pump out diffs from before the synch point
2025-07-02 06:41:17.007         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.007
2025-07-02 06:41:17.007         # do intraline marking on the synch pair
2025-07-02 06:41:17.007         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.007         if eqi is None:
2025-07-02 06:41:17.007             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.007             atags = btags = ""
2025-07-02 06:41:17.007             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.007             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.007                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.008                 if tag == 'replace':
2025-07-02 06:41:17.008                     atags += '^' * la
2025-07-02 06:41:17.008                     btags += '^' * lb
2025-07-02 06:41:17.008                 elif tag == 'delete':
2025-07-02 06:41:17.008                     atags += '-' * la
2025-07-02 06:41:17.008                 elif tag == 'insert':
2025-07-02 06:41:17.008                     btags += '+' * lb
2025-07-02 06:41:17.008                 elif tag == 'equal':
2025-07-02 06:41:17.008                     atags += ' ' * la
2025-07-02 06:41:17.008                     btags += ' ' * lb
2025-07-02 06:41:17.008                 else:
2025-07-02 06:41:17.008                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.008             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.008         else:
2025-07-02 06:41:17.008             # the synch pair is identical
2025-07-02 06:41:17.008             yield '  ' + aelt
2025-07-02 06:41:17.008
2025-07-02 06:41:17.008         # pump out diffs from after the synch point
2025-07-02 06:41:17.008 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.008
2025-07-02 06:41:17.008 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.009 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.009
2025-07-02 06:41:17.009 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.009 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.009 alo = 154, ahi = 1101
2025-07-02 06:41:17.009 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.009 blo = 154, bhi = 1101
2025-07-02 06:41:17.009
2025-07-02 06:41:17.009     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.009         g = []
2025-07-02 06:41:17.009         if alo < ahi:
2025-07-02 06:41:17.009             if blo < bhi:
2025-07-02 06:41:17.009                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.009             else:
2025-07-02 06:41:17.009                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.009         elif blo < bhi:
2025-07-02 06:41:17.009             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.009
2025-07-02 06:41:17.009 >       yield from g
2025-07-02 06:41:17.009
2025-07-02 06:41:17.010 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.010 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.010
2025-07-02 06:41:17.010 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.010 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.010 alo = 154, ahi = 1101
2025-07-02 06:41:17.010 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.010 blo = 154, bhi = 1101
2025-07-02 06:41:17.010
2025-07-02 06:41:17.010     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.010         r"""
2025-07-02 06:41:17.010         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.010         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.010         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.010         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.010
2025-07-02 06:41:17.010         Example:
2025-07-02 06:41:17.010
2025-07-02 06:41:17.010         >>> d = Differ()
2025-07-02 06:41:17.010         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.011         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.011         >>> print(''.join(results), end="")
2025-07-02 06:41:17.011         - abcDefghiJkl
2025-07-02 06:41:17.011         + abcdefGhijkl
2025-07-02 06:41:17.011         """
2025-07-02 06:41:17.011
2025-07-02 06:41:17.011         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.011         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.011         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.011         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.011         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.011
2025-07-02 06:41:17.011         # search for the pair that matches best without being identical
2025-07-02 06:41:17.011         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.011         # on junk -- unless we have to)
2025-07-02 06:41:17.011         for j in range(blo, bhi):
2025-07-02 06:41:17.011             bj = b[j]
2025-07-02 06:41:17.011             cruncher.set_seq2(bj)
2025-07-02 06:41:17.012             for i in range(alo, ahi):
2025-07-02 06:41:17.012                 ai = a[i]
2025-07-02 06:41:17.012                 if ai == bj:
2025-07-02 06:41:17.012                     if eqi is None:
2025-07-02 06:41:17.012                         eqi, eqj = i, j
2025-07-02 06:41:17.012                     continue
2025-07-02 06:41:17.012                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.012                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.012                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.012                 # compares by a factor of 3.
2025-07-02 06:41:17.012                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.012                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.012                 # of the computation is cached by cruncher
2025-07-02 06:41:17.012                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.012                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.012                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.012                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.012         if best_ratio < cutoff:
2025-07-02 06:41:17.013             # no non-identical "pretty close" pair
2025-07-02 06:41:17.013             if eqi is None:
2025-07-02 06:41:17.013                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.013                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.013                 return
2025-07-02 06:41:17.013             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.013             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.013         else:
2025-07-02 06:41:17.013             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.013             eqi = None
2025-07-02 06:41:17.013
2025-07-02 06:41:17.013         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.013         # identical
2025-07-02 06:41:17.013
2025-07-02 06:41:17.013         # pump out diffs from before the synch point
2025-07-02 06:41:17.013         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.013
2025-07-02 06:41:17.013         # do intraline marking on the synch pair
2025-07-02 06:41:17.013         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.013         if eqi is None:
2025-07-02 06:41:17.014             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.014             atags = btags = ""
2025-07-02 06:41:17.014             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.014             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.014                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.014                 if tag == 'replace':
2025-07-02 06:41:17.014                     atags += '^' * la
2025-07-02 06:41:17.014                     btags += '^' * lb
2025-07-02 06:41:17.014                 elif tag == 'delete':
2025-07-02 06:41:17.014                     atags += '-' * la
2025-07-02 06:41:17.014                 elif tag == 'insert':
2025-07-02 06:41:17.014                     btags += '+' * lb
2025-07-02 06:41:17.014                 elif tag == 'equal':
2025-07-02 06:41:17.014                     atags += ' ' * la
2025-07-02 06:41:17.014                     btags += ' ' * lb
2025-07-02 06:41:17.014                 else:
2025-07-02 06:41:17.014                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.014             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.014         else:
2025-07-02 06:41:17.014             # the synch pair is identical
2025-07-02 06:41:17.015             yield '  ' + aelt
2025-07-02 06:41:17.015
2025-07-02 06:41:17.015         # pump out diffs from after the synch point
2025-07-02 06:41:17.015 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.015
2025-07-02 06:41:17.015 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.015 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.015
2025-07-02 06:41:17.015 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.015 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.015 alo = 155, ahi = 1101
2025-07-02 06:41:17.015 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.015 blo = 155, bhi = 1101
2025-07-02 06:41:17.015
2025-07-02 06:41:17.015     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.015         g = []
2025-07-02 06:41:17.015         if alo < ahi:
2025-07-02 06:41:17.015             if blo < bhi:
2025-07-02 06:41:17.015                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.015             else:
2025-07-02 06:41:17.016                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.016         elif blo < bhi:
2025-07-02 06:41:17.016             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.016
2025-07-02 06:41:17.016 >       yield from g
2025-07-02 06:41:17.016
2025-07-02 06:41:17.016 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.016 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.016
2025-07-02 06:41:17.016 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.016 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.016 alo = 155, ahi = 1101
2025-07-02 06:41:17.016 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.016 blo = 155, bhi = 1101
2025-07-02 06:41:17.016
2025-07-02 06:41:17.016     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.016         r"""
2025-07-02 06:41:17.016         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.016         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.016         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.017         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.017
2025-07-02 06:41:17.017         Example:
2025-07-02 06:41:17.017
2025-07-02 06:41:17.017         >>> d = Differ()
2025-07-02 06:41:17.017         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.017         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.017         >>> print(''.join(results), end="")
2025-07-02 06:41:17.017         - abcDefghiJkl
2025-07-02 06:41:17.017         + abcdefGhijkl
2025-07-02 06:41:17.017         """
2025-07-02 06:41:17.017
2025-07-02 06:41:17.017         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.017         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.017         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.017         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.017         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.017
2025-07-02 06:41:17.017         # search for the pair that matches best without being identical
2025-07-02 06:41:17.018         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.018         # on junk -- unless we have to)
2025-07-02 06:41:17.018         for j in range(blo, bhi):
2025-07-02 06:41:17.018             bj = b[j]
2025-07-02 06:41:17.018             cruncher.set_seq2(bj)
2025-07-02 06:41:17.018             for i in range(alo, ahi):
2025-07-02 06:41:17.018                 ai = a[i]
2025-07-02 06:41:17.018                 if ai == bj:
2025-07-02 06:41:17.018                     if eqi is None:
2025-07-02 06:41:17.018                         eqi, eqj = i, j
2025-07-02 06:41:17.018                     continue
2025-07-02 06:41:17.018                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.018                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.018                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.018                 # compares by a factor of 3.
2025-07-02 06:41:17.018                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.018                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.018                 # of the computation is cached by cruncher
2025-07-02 06:41:17.018                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.018                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.019                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.019                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.019         if best_ratio < cutoff:
2025-07-02 06:41:17.019             # no non-identical "pretty close" pair
2025-07-02 06:41:17.019             if eqi is None:
2025-07-02 06:41:17.019                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.019                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.019                 return
2025-07-02 06:41:17.019             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.019             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.019         else:
2025-07-02 06:41:17.019             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.019             eqi = None
2025-07-02 06:41:17.019
2025-07-02 06:41:17.019         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.019         # identical
2025-07-02 06:41:17.019
2025-07-02 06:41:17.019         # pump out diffs from before the synch point
2025-07-02 06:41:17.019         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.019
2025-07-02 06:41:17.019         # do intraline marking on the synch pair
2025-07-02 06:41:17.020         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.020         if eqi is None:
2025-07-02 06:41:17.020             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.020             atags = btags = ""
2025-07-02 06:41:17.020             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.020             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.020                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.020                 if tag == 'replace':
2025-07-02 06:41:17.020                     atags += '^' * la
2025-07-02 06:41:17.020                     btags += '^' * lb
2025-07-02 06:41:17.020                 elif tag == 'delete':
2025-07-02 06:41:17.020                     atags += '-' * la
2025-07-02 06:41:17.020                 elif tag == 'insert':
2025-07-02 06:41:17.020                     btags += '+' * lb
2025-07-02 06:41:17.020                 elif tag == 'equal':
2025-07-02 06:41:17.020                     atags += ' ' * la
2025-07-02 06:41:17.020                     btags += ' ' * lb
2025-07-02 06:41:17.020                 else:
2025-07-02 06:41:17.020                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.021             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.021         else:
2025-07-02 06:41:17.021             # the synch pair is identical
2025-07-02 06:41:17.021             yield '  ' + aelt
2025-07-02 06:41:17.021
2025-07-02 06:41:17.021         # pump out diffs from after the synch point
2025-07-02 06:41:17.021 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.021
2025-07-02 06:41:17.021 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.021 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.021
2025-07-02 06:41:17.021 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.021 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.021 alo = 158, ahi = 1101
2025-07-02 06:41:17.021 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.021 blo = 158, bhi = 1101
2025-07-02 06:41:17.021
2025-07-02 06:41:17.021     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.021         g = []
2025-07-02 06:41:17.022         if alo < ahi:
2025-07-02 06:41:17.022             if blo < bhi:
2025-07-02 06:41:17.022                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.022             else:
2025-07-02 06:41:17.022                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.022         elif blo < bhi:
2025-07-02 06:41:17.022             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.022
2025-07-02 06:41:17.022 >       yield from g
2025-07-02 06:41:17.022
2025-07-02 06:41:17.022 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.022 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.022
2025-07-02 06:41:17.022 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.022 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.022 alo = 158, ahi = 1101
2025-07-02 06:41:17.022 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.022 blo = 158, bhi = 1101
2025-07-02 06:41:17.022
2025-07-02 06:41:17.022     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.023         r"""
2025-07-02 06:41:17.023         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.023         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.023         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.023         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.023
2025-07-02 06:41:17.023         Example:
2025-07-02 06:41:17.023
2025-07-02 06:41:17.023         >>> d = Differ()
2025-07-02 06:41:17.023         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.023         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.023         >>> print(''.join(results), end="")
2025-07-02 06:41:17.023         - abcDefghiJkl
2025-07-02 06:41:17.023         + abcdefGhijkl
2025-07-02 06:41:17.023         """
2025-07-02 06:41:17.023
2025-07-02 06:41:17.023         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.023         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.024         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.024         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.024         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.024
2025-07-02 06:41:17.024         # search for the pair that matches best without being identical
2025-07-02 06:41:17.024         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.024         # on junk -- unless we have to)
2025-07-02 06:41:17.024         for j in range(blo, bhi):
2025-07-02 06:41:17.024             bj = b[j]
2025-07-02 06:41:17.024             cruncher.set_seq2(bj)
2025-07-02 06:41:17.024             for i in range(alo, ahi):
2025-07-02 06:41:17.024                 ai = a[i]
2025-07-02 06:41:17.024                 if ai == bj:
2025-07-02 06:41:17.024                     if eqi is None:
2025-07-02 06:41:17.024                         eqi, eqj = i, j
2025-07-02 06:41:17.024                     continue
2025-07-02 06:41:17.024                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.024                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.024                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.025                 # compares by a factor of 3.
2025-07-02 06:41:17.025                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.025                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.025                 # of the computation is cached by cruncher
2025-07-02 06:41:17.025                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.025                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.025                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.025                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.025         if best_ratio < cutoff:
2025-07-02 06:41:17.025             # no non-identical "pretty close" pair
2025-07-02 06:41:17.025             if eqi is None:
2025-07-02 06:41:17.025                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.025                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.025                 return
2025-07-02 06:41:17.025             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.025             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.025         else:
2025-07-02 06:41:17.025             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.025             eqi = None
2025-07-02 06:41:17.025
2025-07-02 06:41:17.026         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.026         # identical
2025-07-02 06:41:17.026
2025-07-02 06:41:17.026         # pump out diffs from before the synch point
2025-07-02 06:41:17.026         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.026
2025-07-02 06:41:17.026         # do intraline marking on the synch pair
2025-07-02 06:41:17.026         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.026         if eqi is None:
2025-07-02 06:41:17.026             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.026             atags = btags = ""
2025-07-02 06:41:17.026             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.026             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.026                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.026                 if tag == 'replace':
2025-07-02 06:41:17.026                     atags += '^' * la
2025-07-02 06:41:17.026                     btags += '^' * lb
2025-07-02 06:41:17.026                 elif tag == 'delete':
2025-07-02 06:41:17.026                     atags += '-' * la
2025-07-02 06:41:17.026                 elif tag == 'insert':
2025-07-02 06:41:17.026                     btags += '+' * lb
2025-07-02 06:41:17.027                 elif tag == 'equal':
2025-07-02 06:41:17.027                     atags += ' ' * la
2025-07-02 06:41:17.027                     btags += ' ' * lb
2025-07-02 06:41:17.027                 else:
2025-07-02 06:41:17.027                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.027             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.027         else:
2025-07-02 06:41:17.027             # the synch pair is identical
2025-07-02 06:41:17.027             yield '  ' + aelt
2025-07-02 06:41:17.027
2025-07-02 06:41:17.027         # pump out diffs from after the synch point
2025-07-02 06:41:17.027 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.027
2025-07-02 06:41:17.027 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.027 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.027
2025-07-02 06:41:17.027 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.027 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.027 alo = 159, ahi = 1101
2025-07-02 06:41:17.027 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.028 blo = 159, bhi = 1101
2025-07-02 06:41:17.028
2025-07-02 06:41:17.028     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.028         g = []
2025-07-02 06:41:17.028         if alo < ahi:
2025-07-02 06:41:17.028             if blo < bhi:
2025-07-02 06:41:17.028                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.028             else:
2025-07-02 06:41:17.028                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.028         elif blo < bhi:
2025-07-02 06:41:17.028             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.028
2025-07-02 06:41:17.028 >       yield from g
2025-07-02 06:41:17.028
2025-07-02 06:41:17.028 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.028 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.028
2025-07-02 06:41:17.028 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.028 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.028 alo = 159, ahi = 1101
2025-07-02 06:41:17.028 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.029 blo = 159, bhi = 1101
2025-07-02 06:41:17.029
2025-07-02 06:41:17.029     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.029         r"""
2025-07-02 06:41:17.029         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.029         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.029         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.029         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.029
2025-07-02 06:41:17.029         Example:
2025-07-02 06:41:17.029
2025-07-02 06:41:17.029         >>> d = Differ()
2025-07-02 06:41:17.029         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.029         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.029         >>> print(''.join(results), end="")
2025-07-02 06:41:17.030         - abcDefghiJkl
2025-07-02 06:41:17.030         + abcdefGhijkl
2025-07-02 06:41:17.030         """
2025-07-02 06:41:17.030
2025-07-02 06:41:17.030         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.030         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.030         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.030         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.030         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.030
2025-07-02 06:41:17.030         # search for the pair that matches best without being identical
2025-07-02 06:41:17.030         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.030         # on junk -- unless we have to)
2025-07-02 06:41:17.030         for j in range(blo, bhi):
2025-07-02 06:41:17.030             bj = b[j]
2025-07-02 06:41:17.030             cruncher.set_seq2(bj)
2025-07-02 06:41:17.030             for i in range(alo, ahi):
2025-07-02 06:41:17.031                 ai = a[i]
2025-07-02 06:41:17.031                 if ai == bj:
2025-07-02 06:41:17.031                     if eqi is None:
2025-07-02 06:41:17.031                         eqi, eqj = i, j
2025-07-02 06:41:17.031                     continue
2025-07-02 06:41:17.031                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.031                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.031                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.031                 # compares by a factor of 3.
2025-07-02 06:41:17.031                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.031                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.031                 # of the computation is cached by cruncher
2025-07-02 06:41:17.031                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.031                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.031                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.031                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.031         if best_ratio < cutoff:
2025-07-02 06:41:17.031             # no non-identical "pretty close" pair
2025-07-02 06:41:17.031             if eqi is None:
2025-07-02 06:41:17.031                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.032                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.032                 return
2025-07-02 06:41:17.032             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.032             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.032         else:
2025-07-02 06:41:17.032             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.032             eqi = None
2025-07-02 06:41:17.032
2025-07-02 06:41:17.032         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.032         # identical
2025-07-02 06:41:17.032
2025-07-02 06:41:17.032         # pump out diffs from before the synch point
2025-07-02 06:41:17.032         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.032
2025-07-02 06:41:17.032         # do intraline marking on the synch pair
2025-07-02 06:41:17.032         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.032         if eqi is None:
2025-07-02 06:41:17.032             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.032             atags = btags = ""
2025-07-02 06:41:17.032             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.033             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.033                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.033                 if tag == 'replace':
2025-07-02 06:41:17.033                     atags += '^' * la
2025-07-02 06:41:17.033                     btags += '^' * lb
2025-07-02 06:41:17.033                 elif tag == 'delete':
2025-07-02 06:41:17.033                     atags += '-' * la
2025-07-02 06:41:17.033                 elif tag == 'insert':
2025-07-02 06:41:17.033                     btags += '+' * lb
2025-07-02 06:41:17.033                 elif tag == 'equal':
2025-07-02 06:41:17.033                     atags += ' ' * la
2025-07-02 06:41:17.033                     btags += ' ' * lb
2025-07-02 06:41:17.033                 else:
2025-07-02 06:41:17.033                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.033             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.033         else:
2025-07-02 06:41:17.033             # the synch pair is identical
2025-07-02 06:41:17.033             yield '  ' + aelt
2025-07-02 06:41:17.033
2025-07-02 06:41:17.033         # pump out diffs from after the synch point
2025-07-02 06:41:17.034 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.034
2025-07-02 06:41:17.034 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.034 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.034
2025-07-02 06:41:17.034 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.034 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.034 alo = 160, ahi = 1101
2025-07-02 06:41:17.034 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.034 blo = 160, bhi = 1101
2025-07-02 06:41:17.034
2025-07-02 06:41:17.034     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.034         g = []
2025-07-02 06:41:17.034         if alo < ahi:
2025-07-02 06:41:17.034             if blo < bhi:
2025-07-02 06:41:17.034                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.034             else:
2025-07-02 06:41:17.034                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.034         elif blo < bhi:
2025-07-02 06:41:17.034             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.034
2025-07-02 06:41:17.035 >       yield from g
2025-07-02 06:41:17.035
2025-07-02 06:41:17.035 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.035 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.035
2025-07-02 06:41:17.035 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.035 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.035 alo = 160, ahi = 1101
2025-07-02 06:41:17.035 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.035 blo = 160, bhi = 1101
2025-07-02 06:41:17.035
2025-07-02 06:41:17.035     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.035         r"""
2025-07-02 06:41:17.035         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.035         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.035         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.035         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.035
2025-07-02 06:41:17.036         Example:
2025-07-02 06:41:17.036
2025-07-02 06:41:17.036         >>> d = Differ()
2025-07-02 06:41:17.036         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.036         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.036         >>> print(''.join(results), end="")
2025-07-02 06:41:17.036         - abcDefghiJkl
2025-07-02 06:41:17.036         + abcdefGhijkl
2025-07-02 06:41:17.036         """
2025-07-02 06:41:17.036
2025-07-02 06:41:17.036         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.036         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.036         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.036         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.036         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.036
2025-07-02 06:41:17.036         # search for the pair that matches best without being identical
2025-07-02 06:41:17.037         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.037         # on junk -- unless we have to)
2025-07-02 06:41:17.037         for j in range(blo, bhi):
2025-07-02 06:41:17.037             bj = b[j]
2025-07-02 06:41:17.037             cruncher.set_seq2(bj)
2025-07-02 06:41:17.037             for i in range(alo, ahi):
2025-07-02 06:41:17.037                 ai = a[i]
2025-07-02 06:41:17.037                 if ai == bj:
2025-07-02 06:41:17.037                     if eqi is None:
2025-07-02 06:41:17.037                         eqi, eqj = i, j
2025-07-02 06:41:17.037                     continue
2025-07-02 06:41:17.037                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.037                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.037                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.037                 # compares by a factor of 3.
2025-07-02 06:41:17.037                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.037                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.037                 # of the computation is cached by cruncher
2025-07-02 06:41:17.037                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.037                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.037                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.038                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.038         if best_ratio < cutoff:
2025-07-02 06:41:17.038             # no non-identical "pretty close" pair
2025-07-02 06:41:17.038             if eqi is None:
2025-07-02 06:41:17.038                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.038                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.038                 return
2025-07-02 06:41:17.038             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.038             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.038         else:
2025-07-02 06:41:17.038             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.038             eqi = None
2025-07-02 06:41:17.038
2025-07-02 06:41:17.038         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.038         # identical
2025-07-02 06:41:17.038
2025-07-02 06:41:17.038         # pump out diffs from before the synch point
2025-07-02 06:41:17.038         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.039
2025-07-02 06:41:17.039         # do intraline marking on the synch pair
2025-07-02 06:41:17.039         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.039         if eqi is None:
2025-07-02 06:41:17.039             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.039             atags = btags = ""
2025-07-02 06:41:17.039             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.039             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.039                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.039                 if tag == 'replace':
2025-07-02 06:41:17.039                     atags += '^' * la
2025-07-02 06:41:17.039                     btags += '^' * lb
2025-07-02 06:41:17.039                 elif tag == 'delete':
2025-07-02 06:41:17.039                     atags += '-' * la
2025-07-02 06:41:17.039                 elif tag == 'insert':
2025-07-02 06:41:17.039                     btags += '+' * lb
2025-07-02 06:41:17.039                 elif tag == 'equal':
2025-07-02 06:41:17.039                     atags += ' ' * la
2025-07-02 06:41:17.039                     btags += ' ' * lb
2025-07-02 06:41:17.040                 else:
2025-07-02 06:41:17.040                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.040             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.040         else:
2025-07-02 06:41:17.040             # the synch pair is identical
2025-07-02 06:41:17.040             yield '  ' + aelt
2025-07-02 06:41:17.040
2025-07-02 06:41:17.040         # pump out diffs from after the synch point
2025-07-02 06:41:17.040 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.040
2025-07-02 06:41:17.040 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.040 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.040
2025-07-02 06:41:17.040 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.040 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.040 alo = 161, ahi = 1101
2025-07-02 06:41:17.040 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.040 blo = 161, bhi = 1101
2025-07-02 06:41:17.040
2025-07-02 06:41:17.040     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.041         g = []
2025-07-02 06:41:17.041         if alo < ahi:
2025-07-02 06:41:17.041             if blo < bhi:
2025-07-02 06:41:17.041                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.041             else:
2025-07-02 06:41:17.041                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.041         elif blo < bhi:
2025-07-02 06:41:17.041             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.041
2025-07-02 06:41:17.041 >       yield from g
2025-07-02 06:41:17.041
2025-07-02 06:41:17.041 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.041 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.041
2025-07-02 06:41:17.041 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.041 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.041 alo = 161, ahi = 1101
2025-07-02 06:41:17.041 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.041 blo = 161, bhi = 1101
2025-07-02 06:41:17.042
2025-07-02 06:41:17.042     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.042         r"""
2025-07-02 06:41:17.042         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.042         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.042         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.042         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.042
2025-07-02 06:41:17.042         Example:
2025-07-02 06:41:17.042
2025-07-02 06:41:17.042         >>> d = Differ()
2025-07-02 06:41:17.042         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.042         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.042         >>> print(''.join(results), end="")
2025-07-02 06:41:17.042         - abcDefghiJkl
2025-07-02 06:41:17.042         + abcdefGhijkl
2025-07-02 06:41:17.042         """
2025-07-02 06:41:17.042
2025-07-02 06:41:17.043         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.043         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.043         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.043         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.043         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.043
2025-07-02 06:41:17.043         # search for the pair that matches best without being identical
2025-07-02 06:41:17.043         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.043         # on junk -- unless we have to)
2025-07-02 06:41:17.043         for j in range(blo, bhi):
2025-07-02 06:41:17.043             bj = b[j]
2025-07-02 06:41:17.043             cruncher.set_seq2(bj)
2025-07-02 06:41:17.043             for i in range(alo, ahi):
2025-07-02 06:41:17.043                 ai = a[i]
2025-07-02 06:41:17.043                 if ai == bj:
2025-07-02 06:41:17.043                     if eqi is None:
2025-07-02 06:41:17.043                         eqi, eqj = i, j
2025-07-02 06:41:17.043                     continue
2025-07-02 06:41:17.044                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.044                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.044                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.044                 # compares by a factor of 3.
2025-07-02 06:41:17.044                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.044                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.044                 # of the computation is cached by cruncher
2025-07-02 06:41:17.044                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.044                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.044                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.044                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.044         if best_ratio < cutoff:
2025-07-02 06:41:17.044             # no non-identical "pretty close" pair
2025-07-02 06:41:17.044             if eqi is None:
2025-07-02 06:41:17.044                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.044                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.044                 return
2025-07-02 06:41:17.044             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.044             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.044         else:
2025-07-02 06:41:17.045             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.045             eqi = None
2025-07-02 06:41:17.045
2025-07-02 06:41:17.045         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.045         # identical
2025-07-02 06:41:17.045
2025-07-02 06:41:17.045         # pump out diffs from before the synch point
2025-07-02 06:41:17.045         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.045
2025-07-02 06:41:17.045         # do intraline marking on the synch pair
2025-07-02 06:41:17.045         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.045         if eqi is None:
2025-07-02 06:41:17.045             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.045             atags = btags = ""
2025-07-02 06:41:17.045             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.045             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.045                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.045                 if tag == 'replace':
2025-07-02 06:41:17.046                     atags += '^' * la
2025-07-02 06:41:17.046                     btags += '^' * lb
2025-07-02 06:41:17.046                 elif tag == 'delete':
2025-07-02 06:41:17.046                     atags += '-' * la
2025-07-02 06:41:17.046                 elif tag == 'insert':
2025-07-02 06:41:17.046                     btags += '+' * lb
2025-07-02 06:41:17.046                 elif tag == 'equal':
2025-07-02 06:41:17.046                     atags += ' ' * la
2025-07-02 06:41:17.046                     btags += ' ' * lb
2025-07-02 06:41:17.046                 else:
2025-07-02 06:41:17.046                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.046             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.046         else:
2025-07-02 06:41:17.046             # the synch pair is identical
2025-07-02 06:41:17.046             yield '  ' + aelt
2025-07-02 06:41:17.046
2025-07-02 06:41:17.046         # pump out diffs from after the synch point
2025-07-02 06:41:17.046 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.046
2025-07-02 06:41:17.046 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.047 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.047
2025-07-02 06:41:17.047 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.047 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.047 alo = 162, ahi = 1101
2025-07-02 06:41:17.047 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.047 blo = 162, bhi = 1101
2025-07-02 06:41:17.047
2025-07-02 06:41:17.047     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.047         g = []
2025-07-02 06:41:17.047         if alo < ahi:
2025-07-02 06:41:17.047             if blo < bhi:
2025-07-02 06:41:17.047                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.047             else:
2025-07-02 06:41:17.047                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.047         elif blo < bhi:
2025-07-02 06:41:17.047             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.047
2025-07-02 06:41:17.048 >       yield from g
2025-07-02 06:41:17.048
2025-07-02 06:41:17.048 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.048 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.048
2025-07-02 06:41:17.048 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.048 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.048 alo = 162, ahi = 1101
2025-07-02 06:41:17.048 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.048 blo = 162, bhi = 1101
2025-07-02 06:41:17.048
2025-07-02 06:41:17.048     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.048         r"""
2025-07-02 06:41:17.048         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.048         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.048         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.048         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.048
2025-07-02 06:41:17.048         Example:
2025-07-02 06:41:17.049
2025-07-02 06:41:17.049         >>> d = Differ()
2025-07-02 06:41:17.049         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.049         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.049         >>> print(''.join(results), end="")
2025-07-02 06:41:17.049         - abcDefghiJkl
2025-07-02 06:41:17.049         + abcdefGhijkl
2025-07-02 06:41:17.049         """
2025-07-02 06:41:17.049
2025-07-02 06:41:17.049         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.049         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.049         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.049         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.049         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.049
2025-07-02 06:41:17.049         # search for the pair that matches best without being identical
2025-07-02 06:41:17.049         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.049         # on junk -- unless we have to)
2025-07-02 06:41:17.050         for j in range(blo, bhi):
2025-07-02 06:41:17.050             bj = b[j]
2025-07-02 06:41:17.050             cruncher.set_seq2(bj)
2025-07-02 06:41:17.050             for i in range(alo, ahi):
2025-07-02 06:41:17.050                 ai = a[i]
2025-07-02 06:41:17.050                 if ai == bj:
2025-07-02 06:41:17.050                     if eqi is None:
2025-07-02 06:41:17.050                         eqi, eqj = i, j
2025-07-02 06:41:17.050                     continue
2025-07-02 06:41:17.050                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.050                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.050                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.050                 # compares by a factor of 3.
2025-07-02 06:41:17.050                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.050                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.050                 # of the computation is cached by cruncher
2025-07-02 06:41:17.050                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.050                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.050                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.050                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.050         if best_ratio < cutoff:
2025-07-02 06:41:17.051             # no non-identical "pretty close" pair
2025-07-02 06:41:17.051             if eqi is None:
2025-07-02 06:41:17.051                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.051                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.051                 return
2025-07-02 06:41:17.051             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.051             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.051         else:
2025-07-02 06:41:17.051             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.051             eqi = None
2025-07-02 06:41:17.051
2025-07-02 06:41:17.051         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.051         # identical
2025-07-02 06:41:17.051
2025-07-02 06:41:17.051         # pump out diffs from before the synch point
2025-07-02 06:41:17.051         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.051
2025-07-02 06:41:17.051         # do intraline marking on the synch pair
2025-07-02 06:41:17.051         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.051         if eqi is None:
2025-07-02 06:41:17.052             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.052             atags = btags = ""
2025-07-02 06:41:17.052             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.052             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.052                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.052                 if tag == 'replace':
2025-07-02 06:41:17.052                     atags += '^' * la
2025-07-02 06:41:17.052                     btags += '^' * lb
2025-07-02 06:41:17.052                 elif tag == 'delete':
2025-07-02 06:41:17.052                     atags += '-' * la
2025-07-02 06:41:17.052                 elif tag == 'insert':
2025-07-02 06:41:17.052                     btags += '+' * lb
2025-07-02 06:41:17.052                 elif tag == 'equal':
2025-07-02 06:41:17.052                     atags += ' ' * la
2025-07-02 06:41:17.052                     btags += ' ' * lb
2025-07-02 06:41:17.052                 else:
2025-07-02 06:41:17.052                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.052             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.052         else:
2025-07-02 06:41:17.052             # the synch pair is identical
2025-07-02 06:41:17.052             yield '  ' + aelt
2025-07-02 06:41:17.053
2025-07-02 06:41:17.053         # pump out diffs from after the synch point
2025-07-02 06:41:17.053 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.053
2025-07-02 06:41:17.053 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.053 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.053
2025-07-02 06:41:17.053 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.053 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.053 alo = 163, ahi = 1101
2025-07-02 06:41:17.053 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.053 blo = 163, bhi = 1101
2025-07-02 06:41:17.053
2025-07-02 06:41:17.053     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.053         g = []
2025-07-02 06:41:17.053         if alo < ahi:
2025-07-02 06:41:17.053             if blo < bhi:
2025-07-02 06:41:17.053                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.053             else:
2025-07-02 06:41:17.053                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.054         elif blo < bhi:
2025-07-02 06:41:17.054             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.054
2025-07-02 06:41:17.054 >       yield from g
2025-07-02 06:41:17.054
2025-07-02 06:41:17.054 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.054 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.054
2025-07-02 06:41:17.054 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.054 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.054 alo = 163, ahi = 1101
2025-07-02 06:41:17.054 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.054 blo = 163, bhi = 1101
2025-07-02 06:41:17.054
2025-07-02 06:41:17.054     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.054         r"""
2025-07-02 06:41:17.054         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.054         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.054         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.054         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.055
2025-07-02 06:41:17.055         Example:
2025-07-02 06:41:17.055
2025-07-02 06:41:17.055         >>> d = Differ()
2025-07-02 06:41:17.055         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.055         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.055         >>> print(''.join(results), end="")
2025-07-02 06:41:17.055         - abcDefghiJkl
2025-07-02 06:41:17.055         + abcdefGhijkl
2025-07-02 06:41:17.055         """
2025-07-02 06:41:17.055
2025-07-02 06:41:17.055         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.055         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.055         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.055         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.055         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.055
2025-07-02 06:41:17.055         # search for the pair that matches best without being identical
2025-07-02 06:41:17.056         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.056         # on junk -- unless we have to)
2025-07-02 06:41:17.056         for j in range(blo, bhi):
2025-07-02 06:41:17.056             bj = b[j]
2025-07-02 06:41:17.056             cruncher.set_seq2(bj)
2025-07-02 06:41:17.056             for i in range(alo, ahi):
2025-07-02 06:41:17.056                 ai = a[i]
2025-07-02 06:41:17.056                 if ai == bj:
2025-07-02 06:41:17.056                     if eqi is None:
2025-07-02 06:41:17.056                         eqi, eqj = i, j
2025-07-02 06:41:17.056                     continue
2025-07-02 06:41:17.056                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.056                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.056                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.056                 # compares by a factor of 3.
2025-07-02 06:41:17.056                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.056                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.056                 # of the computation is cached by cruncher
2025-07-02 06:41:17.056                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.057                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.057                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.057                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.057         if best_ratio < cutoff:
2025-07-02 06:41:17.057             # no non-identical "pretty close" pair
2025-07-02 06:41:17.057             if eqi is None:
2025-07-02 06:41:17.057                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.057                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.057                 return
2025-07-02 06:41:17.057             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.057             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.057         else:
2025-07-02 06:41:17.057             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.057             eqi = None
2025-07-02 06:41:17.057
2025-07-02 06:41:17.057         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.057         # identical
2025-07-02 06:41:17.057
2025-07-02 06:41:17.057         # pump out diffs from before the synch point
2025-07-02 06:41:17.057         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.058
2025-07-02 06:41:17.058         # do intraline marking on the synch pair
2025-07-02 06:41:17.058         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.058         if eqi is None:
2025-07-02 06:41:17.058             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.058             atags = btags = ""
2025-07-02 06:41:17.058             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.058             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.058                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.058                 if tag == 'replace':
2025-07-02 06:41:17.058                     atags += '^' * la
2025-07-02 06:41:17.058                     btags += '^' * lb
2025-07-02 06:41:17.058                 elif tag == 'delete':
2025-07-02 06:41:17.058                     atags += '-' * la
2025-07-02 06:41:17.058                 elif tag == 'insert':
2025-07-02 06:41:17.058                     btags += '+' * lb
2025-07-02 06:41:17.058                 elif tag == 'equal':
2025-07-02 06:41:17.058                     atags += ' ' * la
2025-07-02 06:41:17.058                     btags += ' ' * lb
2025-07-02 06:41:17.058                 else:
2025-07-02 06:41:17.059                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.059             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.059         else:
2025-07-02 06:41:17.059             # the synch pair is identical
2025-07-02 06:41:17.059             yield '  ' + aelt
2025-07-02 06:41:17.059
2025-07-02 06:41:17.059         # pump out diffs from after the synch point
2025-07-02 06:41:17.059 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.059
2025-07-02 06:41:17.059 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.059 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.059
2025-07-02 06:41:17.059 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.059 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.059 alo = 164, ahi = 1101
2025-07-02 06:41:17.059 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.059 blo = 164, bhi = 1101
2025-07-02 06:41:17.059
2025-07-02 06:41:17.059     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.059         g = []
2025-07-02 06:41:17.060         if alo < ahi:
2025-07-02 06:41:17.060             if blo < bhi:
2025-07-02 06:41:17.060                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.060             else:
2025-07-02 06:41:17.060                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.060         elif blo < bhi:
2025-07-02 06:41:17.060             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.060
2025-07-02 06:41:17.060 >       yield from g
2025-07-02 06:41:17.060
2025-07-02 06:41:17.060 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.060 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.060
2025-07-02 06:41:17.060 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.060 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.060 alo = 164, ahi = 1101
2025-07-02 06:41:17.060 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.060 blo = 164, bhi = 1101
2025-07-02 06:41:17.060
2025-07-02 06:41:17.060     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.060         r"""
2025-07-02 06:41:17.061         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.061         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.061         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.061         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.061
2025-07-02 06:41:17.061         Example:
2025-07-02 06:41:17.061
2025-07-02 06:41:17.061         >>> d = Differ()
2025-07-02 06:41:17.061         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.061         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.061         >>> print(''.join(results), end="")
2025-07-02 06:41:17.061         - abcDefghiJkl
2025-07-02 06:41:17.061         + abcdefGhijkl
2025-07-02 06:41:17.061         """
2025-07-02 06:41:17.062
2025-07-02 06:41:17.062         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.062         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.062         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.062         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.062         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.062
2025-07-02 06:41:17.062         # search for the pair that matches best without being identical
2025-07-02 06:41:17.062         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.062         # on junk -- unless we have to)
2025-07-02 06:41:17.062         for j in range(blo, bhi):
2025-07-02 06:41:17.062             bj = b[j]
2025-07-02 06:41:17.062             cruncher.set_seq2(bj)
2025-07-02 06:41:17.062             for i in range(alo, ahi):
2025-07-02 06:41:17.062                 ai = a[i]
2025-07-02 06:41:17.062                 if ai == bj:
2025-07-02 06:41:17.062                     if eqi is None:
2025-07-02 06:41:17.062                         eqi, eqj = i, j
2025-07-02 06:41:17.062                     continue
2025-07-02 06:41:17.062                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.063                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.063                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.063                 # compares by a factor of 3.
2025-07-02 06:41:17.063                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.063                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.063                 # of the computation is cached by cruncher
2025-07-02 06:41:17.063                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.063                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.063                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.063                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.063         if best_ratio < cutoff:
2025-07-02 06:41:17.063             # no non-identical "pretty close" pair
2025-07-02 06:41:17.063             if eqi is None:
2025-07-02 06:41:17.063                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.063                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.063                 return
2025-07-02 06:41:17.063             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.063             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.063         else:
2025-07-02 06:41:17.064             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.064             eqi = None
2025-07-02 06:41:17.064
2025-07-02 06:41:17.064         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.064         # identical
2025-07-02 06:41:17.064
2025-07-02 06:41:17.064         # pump out diffs from before the synch point
2025-07-02 06:41:17.064         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.064
2025-07-02 06:41:17.064         # do intraline marking on the synch pair
2025-07-02 06:41:17.064         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.064         if eqi is None:
2025-07-02 06:41:17.064             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.064             atags = btags = ""
2025-07-02 06:41:17.064             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.064             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.064                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.064                 if tag == 'replace':
2025-07-02 06:41:17.064                     atags += '^' * la
2025-07-02 06:41:17.065                     btags += '^' * lb
2025-07-02 06:41:17.065                 elif tag == 'delete':
2025-07-02 06:41:17.065                     atags += '-' * la
2025-07-02 06:41:17.065                 elif tag == 'insert':
2025-07-02 06:41:17.065                     btags += '+' * lb
2025-07-02 06:41:17.065                 elif tag == 'equal':
2025-07-02 06:41:17.065                     atags += ' ' * la
2025-07-02 06:41:17.065                     btags += ' ' * lb
2025-07-02 06:41:17.065                 else:
2025-07-02 06:41:17.065                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.065             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.065         else:
2025-07-02 06:41:17.065             # the synch pair is identical
2025-07-02 06:41:17.065             yield '  ' + aelt
2025-07-02 06:41:17.065
2025-07-02 06:41:17.065         # pump out diffs from after the synch point
2025-07-02 06:41:17.065 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.065
2025-07-02 06:41:17.065 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.066 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.066
2025-07-02 06:41:17.066 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.066 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.066 alo = 165, ahi = 1101
2025-07-02 06:41:17.066 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.066 blo = 165, bhi = 1101
2025-07-02 06:41:17.066
2025-07-02 06:41:17.066     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.066         g = []
2025-07-02 06:41:17.066         if alo < ahi:
2025-07-02 06:41:17.066             if blo < bhi:
2025-07-02 06:41:17.066                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.066             else:
2025-07-02 06:41:17.066                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.066         elif blo < bhi:
2025-07-02 06:41:17.066             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.066
2025-07-02 06:41:17.066 >       yield from g
2025-07-02 06:41:17.067
2025-07-02 06:41:17.067 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.067 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.067
2025-07-02 06:41:17.067 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.067 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.067 alo = 165, ahi = 1101
2025-07-02 06:41:17.067 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.067 blo = 165, bhi = 1101
2025-07-02 06:41:17.067
2025-07-02 06:41:17.067     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.067         r"""
2025-07-02 06:41:17.067         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.067         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.067         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.067         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.067
2025-07-02 06:41:17.067         Example:
2025-07-02 06:41:17.067
2025-07-02 06:41:17.068         >>> d = Differ()
2025-07-02 06:41:17.068         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.068         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.068         >>> print(''.join(results), end="")
2025-07-02 06:41:17.068         - abcDefghiJkl
2025-07-02 06:41:17.068         + abcdefGhijkl
2025-07-02 06:41:17.068         """
2025-07-02 06:41:17.068
2025-07-02 06:41:17.068         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.068         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.068         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.068         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.068         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.068
2025-07-02 06:41:17.068         # search for the pair that matches best without being identical
2025-07-02 06:41:17.068         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.068         # on junk -- unless we have to)
2025-07-02 06:41:17.069         for j in range(blo, bhi):
2025-07-02 06:41:17.069             bj = b[j]
2025-07-02 06:41:17.069             cruncher.set_seq2(bj)
2025-07-02 06:41:17.069             for i in range(alo, ahi):
2025-07-02 06:41:17.069                 ai = a[i]
2025-07-02 06:41:17.069                 if ai == bj:
2025-07-02 06:41:17.069                     if eqi is None:
2025-07-02 06:41:17.069                         eqi, eqj = i, j
2025-07-02 06:41:17.069                     continue
2025-07-02 06:41:17.069                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.069                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.069                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.069                 # compares by a factor of 3.
2025-07-02 06:41:17.069                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.069                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.069                 # of the computation is cached by cruncher
2025-07-02 06:41:17.069                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.069                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.069                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.070                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.070         if best_ratio < cutoff:
2025-07-02 06:41:17.070             # no non-identical "pretty close" pair
2025-07-02 06:41:17.070             if eqi is None:
2025-07-02 06:41:17.070                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.070                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.070                 return
2025-07-02 06:41:17.070             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.070             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.070         else:
2025-07-02 06:41:17.070             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.070             eqi = None
2025-07-02 06:41:17.070
2025-07-02 06:41:17.070         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.070         # identical
2025-07-02 06:41:17.070
2025-07-02 06:41:17.070         # pump out diffs from before the synch point
2025-07-02 06:41:17.070         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.070
2025-07-02 06:41:17.070         # do intraline marking on the synch pair
2025-07-02 06:41:17.071         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.071         if eqi is None:
2025-07-02 06:41:17.071             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.071             atags = btags = ""
2025-07-02 06:41:17.071             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.071             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.071                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.071                 if tag == 'replace':
2025-07-02 06:41:17.071                     atags += '^' * la
2025-07-02 06:41:17.071                     btags += '^' * lb
2025-07-02 06:41:17.071                 elif tag == 'delete':
2025-07-02 06:41:17.071                     atags += '-' * la
2025-07-02 06:41:17.071                 elif tag == 'insert':
2025-07-02 06:41:17.071                     btags += '+' * lb
2025-07-02 06:41:17.071                 elif tag == 'equal':
2025-07-02 06:41:17.071                     atags += ' ' * la
2025-07-02 06:41:17.071                     btags += ' ' * lb
2025-07-02 06:41:17.071                 else:
2025-07-02 06:41:17.071                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.071             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.072         else:
2025-07-02 06:41:17.072             # the synch pair is identical
2025-07-02 06:41:17.072             yield '  ' + aelt
2025-07-02 06:41:17.072
2025-07-02 06:41:17.072         # pump out diffs from after the synch point
2025-07-02 06:41:17.072 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.072
2025-07-02 06:41:17.072 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.072 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.072
2025-07-02 06:41:17.072 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.072 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.072 alo = 166, ahi = 1101
2025-07-02 06:41:17.072 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.072 blo = 166, bhi = 1101
2025-07-02 06:41:17.072
2025-07-02 06:41:17.072     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.072         g = []
2025-07-02 06:41:17.072         if alo < ahi:
2025-07-02 06:41:17.072             if blo < bhi:
2025-07-02 06:41:17.073                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.073             else:
2025-07-02 06:41:17.073                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.073         elif blo < bhi:
2025-07-02 06:41:17.073             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.073
2025-07-02 06:41:17.073 >       yield from g
2025-07-02 06:41:17.073
2025-07-02 06:41:17.073 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.073 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.073
2025-07-02 06:41:17.073 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.073 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.073 alo = 166, ahi = 1101
2025-07-02 06:41:17.073 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.073 blo = 166, bhi = 1101
2025-07-02 06:41:17.073
2025-07-02 06:41:17.073     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.074         r"""
2025-07-02 06:41:17.074         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.074         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.074         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.074         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.074
2025-07-02 06:41:17.074         Example:
2025-07-02 06:41:17.074
2025-07-02 06:41:17.074         >>> d = Differ()
2025-07-02 06:41:17.074         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.074         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.074         >>> print(''.join(results), end="")
2025-07-02 06:41:17.074         - abcDefghiJkl
2025-07-02 06:41:17.074         + abcdefGhijkl
2025-07-02 06:41:17.074         """
2025-07-02 06:41:17.074
2025-07-02 06:41:17.074         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.074         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.075         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.075         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.075         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.075
2025-07-02 06:41:17.075         # search for the pair that matches best without being identical
2025-07-02 06:41:17.075         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.075         # on junk -- unless we have to)
2025-07-02 06:41:17.075         for j in range(blo, bhi):
2025-07-02 06:41:17.075             bj = b[j]
2025-07-02 06:41:17.075             cruncher.set_seq2(bj)
2025-07-02 06:41:17.075             for i in range(alo, ahi):
2025-07-02 06:41:17.075                 ai = a[i]
2025-07-02 06:41:17.075                 if ai == bj:
2025-07-02 06:41:17.075                     if eqi is None:
2025-07-02 06:41:17.075                         eqi, eqj = i, j
2025-07-02 06:41:17.075                     continue
2025-07-02 06:41:17.075                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.075                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.075                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.076                 # compares by a factor of 3.
2025-07-02 06:41:17.076                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.076                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.076                 # of the computation is cached by cruncher
2025-07-02 06:41:17.076                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.076                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.076                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.076                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.076         if best_ratio < cutoff:
2025-07-02 06:41:17.076             # no non-identical "pretty close" pair
2025-07-02 06:41:17.076             if eqi is None:
2025-07-02 06:41:17.076                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.076                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.076                 return
2025-07-02 06:41:17.076             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.076             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.076         else:
2025-07-02 06:41:17.076             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.076             eqi = None
2025-07-02 06:41:17.076
2025-07-02 06:41:17.076         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.077         # identical
2025-07-02 06:41:17.077
2025-07-02 06:41:17.077         # pump out diffs from before the synch point
2025-07-02 06:41:17.077         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.077
2025-07-02 06:41:17.077         # do intraline marking on the synch pair
2025-07-02 06:41:17.077         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.077         if eqi is None:
2025-07-02 06:41:17.077             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.077             atags = btags = ""
2025-07-02 06:41:17.077             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.077             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.077                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.077                 if tag == 'replace':
2025-07-02 06:41:17.077                     atags += '^' * la
2025-07-02 06:41:17.077                     btags += '^' * lb
2025-07-02 06:41:17.077                 elif tag == 'delete':
2025-07-02 06:41:17.077                     atags += '-' * la
2025-07-02 06:41:17.078                 elif tag == 'insert':
2025-07-02 06:41:17.078                     btags += '+' * lb
2025-07-02 06:41:17.078                 elif tag == 'equal':
2025-07-02 06:41:17.078                     atags += ' ' * la
2025-07-02 06:41:17.078                     btags += ' ' * lb
2025-07-02 06:41:17.078                 else:
2025-07-02 06:41:17.078                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.078             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.078         else:
2025-07-02 06:41:17.078             # the synch pair is identical
2025-07-02 06:41:17.078             yield '  ' + aelt
2025-07-02 06:41:17.078
2025-07-02 06:41:17.078         # pump out diffs from after the synch point
2025-07-02 06:41:17.078 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.078
2025-07-02 06:41:17.078 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.078 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.078
2025-07-02 06:41:17.078 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.078 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.078 alo = 167, ahi = 1101
2025-07-02 06:41:17.079 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.079 blo = 167, bhi = 1101
2025-07-02 06:41:17.079
2025-07-02 06:41:17.079     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.079         g = []
2025-07-02 06:41:17.079         if alo < ahi:
2025-07-02 06:41:17.079             if blo < bhi:
2025-07-02 06:41:17.079                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.079             else:
2025-07-02 06:41:17.079                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.079         elif blo < bhi:
2025-07-02 06:41:17.079             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.079
2025-07-02 06:41:17.079 >       yield from g
2025-07-02 06:41:17.079
2025-07-02 06:41:17.079 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.079 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.079
2025-07-02 06:41:17.079 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.079 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.080 alo = 167, ahi = 1101
2025-07-02 06:41:17.080 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.080 blo = 167, bhi = 1101
2025-07-02 06:41:17.080
2025-07-02 06:41:17.080     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.080         r"""
2025-07-02 06:41:17.080         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.080         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.080         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.080         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.080
2025-07-02 06:41:17.080         Example:
2025-07-02 06:41:17.080
2025-07-02 06:41:17.080         >>> d = Differ()
2025-07-02 06:41:17.080         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.080         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.080         >>> print(''.join(results), end="")
2025-07-02 06:41:17.080         - abcDefghiJkl
2025-07-02 06:41:17.080         + abcdefGhijkl
2025-07-02 06:41:17.081         """
2025-07-02 06:41:17.081
2025-07-02 06:41:17.081         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.081         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.081         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.081         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.081         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.081
2025-07-02 06:41:17.081         # search for the pair that matches best without being identical
2025-07-02 06:41:17.081         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.081         # on junk -- unless we have to)
2025-07-02 06:41:17.081         for j in range(blo, bhi):
2025-07-02 06:41:17.081             bj = b[j]
2025-07-02 06:41:17.081             cruncher.set_seq2(bj)
2025-07-02 06:41:17.081             for i in range(alo, ahi):
2025-07-02 06:41:17.081                 ai = a[i]
2025-07-02 06:41:17.081                 if ai == bj:
2025-07-02 06:41:17.081                     if eqi is None:
2025-07-02 06:41:17.081                         eqi, eqj = i, j
2025-07-02 06:41:17.081                     continue
2025-07-02 06:41:17.082                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.082                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.082                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.082                 # compares by a factor of 3.
2025-07-02 06:41:17.082                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.082                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.082                 # of the computation is cached by cruncher
2025-07-02 06:41:17.082                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.082                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.082                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.082                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.082         if best_ratio < cutoff:
2025-07-02 06:41:17.082             # no non-identical "pretty close" pair
2025-07-02 06:41:17.082             if eqi is None:
2025-07-02 06:41:17.082                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.082                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.082                 return
2025-07-02 06:41:17.082             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.082             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.083         else:
2025-07-02 06:41:17.083             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.083             eqi = None
2025-07-02 06:41:17.083
2025-07-02 06:41:17.083         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.083         # identical
2025-07-02 06:41:17.083
2025-07-02 06:41:17.083         # pump out diffs from before the synch point
2025-07-02 06:41:17.083         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.083
2025-07-02 06:41:17.083         # do intraline marking on the synch pair
2025-07-02 06:41:17.083         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.083         if eqi is None:
2025-07-02 06:41:17.083             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.083             atags = btags = ""
2025-07-02 06:41:17.083             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.083             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.083                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.083                 if tag == 'replace':
2025-07-02 06:41:17.083                     atags += '^' * la
2025-07-02 06:41:17.084                     btags += '^' * lb
2025-07-02 06:41:17.084                 elif tag == 'delete':
2025-07-02 06:41:17.084                     atags += '-' * la
2025-07-02 06:41:17.084                 elif tag == 'insert':
2025-07-02 06:41:17.084                     btags += '+' * lb
2025-07-02 06:41:17.084                 elif tag == 'equal':
2025-07-02 06:41:17.084                     atags += ' ' * la
2025-07-02 06:41:17.084                     btags += ' ' * lb
2025-07-02 06:41:17.084                 else:
2025-07-02 06:41:17.084                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.084             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.084         else:
2025-07-02 06:41:17.084             # the synch pair is identical
2025-07-02 06:41:17.084             yield '  ' + aelt
2025-07-02 06:41:17.084
2025-07-02 06:41:17.084         # pump out diffs from after the synch point
2025-07-02 06:41:17.084 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.084
2025-07-02 06:41:17.084 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.084 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.085
2025-07-02 06:41:17.085 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.085 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.085 alo = 168, ahi = 1101
2025-07-02 06:41:17.085 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.085 blo = 168, bhi = 1101
2025-07-02 06:41:17.085
2025-07-02 06:41:17.085     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.085         g = []
2025-07-02 06:41:17.085         if alo < ahi:
2025-07-02 06:41:17.085             if blo < bhi:
2025-07-02 06:41:17.085                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.085             else:
2025-07-02 06:41:17.085                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.085         elif blo < bhi:
2025-07-02 06:41:17.085             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.085
2025-07-02 06:41:17.085 >       yield from g
2025-07-02 06:41:17.085
2025-07-02 06:41:17.085 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.086 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.086
2025-07-02 06:41:17.086 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.086 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.086 alo = 168, ahi = 1101
2025-07-02 06:41:17.086 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.086 blo = 168, bhi = 1101
2025-07-02 06:41:17.086
2025-07-02 06:41:17.086     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.086         r"""
2025-07-02 06:41:17.086         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.086         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.086         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.086         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.086
2025-07-02 06:41:17.086         Example:
2025-07-02 06:41:17.086
2025-07-02 06:41:17.086         >>> d = Differ()
2025-07-02 06:41:17.086         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.086         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.086         >>> print(''.join(results), end="")
2025-07-02 06:41:17.087         - abcDefghiJkl
2025-07-02 06:41:17.087         + abcdefGhijkl
2025-07-02 06:41:17.087         """
2025-07-02 06:41:17.087
2025-07-02 06:41:17.087         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.087         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.087         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.087         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.087         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.087
2025-07-02 06:41:17.087         # search for the pair that matches best without being identical
2025-07-02 06:41:17.087         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.087         # on junk -- unless we have to)
2025-07-02 06:41:17.087         for j in range(blo, bhi):
2025-07-02 06:41:17.087             bj = b[j]
2025-07-02 06:41:17.087             cruncher.set_seq2(bj)
2025-07-02 06:41:17.087             for i in range(alo, ahi):
2025-07-02 06:41:17.087                 ai = a[i]
2025-07-02 06:41:17.088                 if ai == bj:
2025-07-02 06:41:17.088                     if eqi is None:
2025-07-02 06:41:17.088                         eqi, eqj = i, j
2025-07-02 06:41:17.088                     continue
2025-07-02 06:41:17.088                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.088                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.088                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.088                 # compares by a factor of 3.
2025-07-02 06:41:17.088                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.088                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.088                 # of the computation is cached by cruncher
2025-07-02 06:41:17.088                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.088                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.088                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.088                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.088         if best_ratio < cutoff:
2025-07-02 06:41:17.088             # no non-identical "pretty close" pair
2025-07-02 06:41:17.088             if eqi is None:
2025-07-02 06:41:17.088                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.089                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.089                 return
2025-07-02 06:41:17.089             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.089             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.089         else:
2025-07-02 06:41:17.089             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.089             eqi = None
2025-07-02 06:41:17.089
2025-07-02 06:41:17.089         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.089         # identical
2025-07-02 06:41:17.089
2025-07-02 06:41:17.089         # pump out diffs from before the synch point
2025-07-02 06:41:17.089         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.089
2025-07-02 06:41:17.089         # do intraline marking on the synch pair
2025-07-02 06:41:17.089         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.089         if eqi is None:
2025-07-02 06:41:17.089             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.089             atags = btags = ""
2025-07-02 06:41:17.089             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.089             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.090                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.090                 if tag == 'replace':
2025-07-02 06:41:17.090                     atags += '^' * la
2025-07-02 06:41:17.090                     btags += '^' * lb
2025-07-02 06:41:17.090                 elif tag == 'delete':
2025-07-02 06:41:17.090                     atags += '-' * la
2025-07-02 06:41:17.090                 elif tag == 'insert':
2025-07-02 06:41:17.090                     btags += '+' * lb
2025-07-02 06:41:17.090                 elif tag == 'equal':
2025-07-02 06:41:17.090                     atags += ' ' * la
2025-07-02 06:41:17.090                     btags += ' ' * lb
2025-07-02 06:41:17.090                 else:
2025-07-02 06:41:17.090                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.090             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.090         else:
2025-07-02 06:41:17.090             # the synch pair is identical
2025-07-02 06:41:17.090             yield '  ' + aelt
2025-07-02 06:41:17.090
2025-07-02 06:41:17.090         # pump out diffs from after the synch point
2025-07-02 06:41:17.090 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.091
2025-07-02 06:41:17.091 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.091 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.091
2025-07-02 06:41:17.091 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.091 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.091 alo = 169, ahi = 1101
2025-07-02 06:41:17.091 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.091 blo = 169, bhi = 1101
2025-07-02 06:41:17.091
2025-07-02 06:41:17.091     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.091         g = []
2025-07-02 06:41:17.091         if alo < ahi:
2025-07-02 06:41:17.091             if blo < bhi:
2025-07-02 06:41:17.091                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.091             else:
2025-07-02 06:41:17.091                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.091         elif blo < bhi:
2025-07-02 06:41:17.091             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092 >       yield from g
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.092 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.092 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.092 alo = 169, ahi = 1101
2025-07-02 06:41:17.092 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.092 blo = 169, bhi = 1101
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.092         r"""
2025-07-02 06:41:17.092         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.092         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.092         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.092         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.092
2025-07-02 06:41:17.092         Example:
2025-07-02 06:41:17.093
2025-07-02 06:41:17.093         >>> d = Differ()
2025-07-02 06:41:17.093         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.093         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.093         >>> print(''.join(results), end="")
2025-07-02 06:41:17.093         - abcDefghiJkl
2025-07-02 06:41:17.093         + abcdefGhijkl
2025-07-02 06:41:17.093         """
2025-07-02 06:41:17.093
2025-07-02 06:41:17.093         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.093         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.093         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.093         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.093         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.093
2025-07-02 06:41:17.093         # search for the pair that matches best without being identical
2025-07-02 06:41:17.094         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.094         # on junk -- unless we have to)
2025-07-02 06:41:17.094         for j in range(blo, bhi):
2025-07-02 06:41:17.094             bj = b[j]
2025-07-02 06:41:17.094             cruncher.set_seq2(bj)
2025-07-02 06:41:17.094             for i in range(alo, ahi):
2025-07-02 06:41:17.094                 ai = a[i]
2025-07-02 06:41:17.094                 if ai == bj:
2025-07-02 06:41:17.094                     if eqi is None:
2025-07-02 06:41:17.094                         eqi, eqj = i, j
2025-07-02 06:41:17.094                     continue
2025-07-02 06:41:17.094                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.094                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.094                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.094                 # compares by a factor of 3.
2025-07-02 06:41:17.094                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.094                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.094                 # of the computation is cached by cruncher
2025-07-02 06:41:17.094                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.094                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.095                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.095                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.095         if best_ratio < cutoff:
2025-07-02 06:41:17.095             # no non-identical "pretty close" pair
2025-07-02 06:41:17.095             if eqi is None:
2025-07-02 06:41:17.095                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.095                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.095                 return
2025-07-02 06:41:17.095             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.095             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.095         else:
2025-07-02 06:41:17.095             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.095             eqi = None
2025-07-02 06:41:17.095
2025-07-02 06:41:17.095         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.095         # identical
2025-07-02 06:41:17.095
2025-07-02 06:41:17.095         # pump out diffs from before the synch point
2025-07-02 06:41:17.095         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.095
2025-07-02 06:41:17.096         # do intraline marking on the synch pair
2025-07-02 06:41:17.096         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.096         if eqi is None:
2025-07-02 06:41:17.096             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.096             atags = btags = ""
2025-07-02 06:41:17.096             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.096             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.096                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.096                 if tag == 'replace':
2025-07-02 06:41:17.096                     atags += '^' * la
2025-07-02 06:41:17.096                     btags += '^' * lb
2025-07-02 06:41:17.096                 elif tag == 'delete':
2025-07-02 06:41:17.096                     atags += '-' * la
2025-07-02 06:41:17.096                 elif tag == 'insert':
2025-07-02 06:41:17.096                     btags += '+' * lb
2025-07-02 06:41:17.096                 elif tag == 'equal':
2025-07-02 06:41:17.096                     atags += ' ' * la
2025-07-02 06:41:17.096                     btags += ' ' * lb
2025-07-02 06:41:17.096                 else:
2025-07-02 06:41:17.096                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.096             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.097         else:
2025-07-02 06:41:17.097             # the synch pair is identical
2025-07-02 06:41:17.097             yield '  ' + aelt
2025-07-02 06:41:17.097
2025-07-02 06:41:17.097         # pump out diffs from after the synch point
2025-07-02 06:41:17.097 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.097
2025-07-02 06:41:17.097 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.097 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.097
2025-07-02 06:41:17.097 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.097 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.097 alo = 170, ahi = 1101
2025-07-02 06:41:17.097 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.097 blo = 170, bhi = 1101
2025-07-02 06:41:17.097
2025-07-02 06:41:17.097     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.097         g = []
2025-07-02 06:41:17.097         if alo < ahi:
2025-07-02 06:41:17.097             if blo < bhi:
2025-07-02 06:41:17.098                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.098             else:
2025-07-02 06:41:17.098                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.098         elif blo < bhi:
2025-07-02 06:41:17.098             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.098
2025-07-02 06:41:17.098 >       yield from g
2025-07-02 06:41:17.098
2025-07-02 06:41:17.098 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.098 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.098
2025-07-02 06:41:17.098 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.098 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.098 alo = 170, ahi = 1101
2025-07-02 06:41:17.098 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.098 blo = 170, bhi = 1101
2025-07-02 06:41:17.098
2025-07-02 06:41:17.098     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.098         r"""
2025-07-02 06:41:17.098         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.099         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.099         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.099         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.099
2025-07-02 06:41:17.099         Example:
2025-07-02 06:41:17.099
2025-07-02 06:41:17.099         >>> d = Differ()
2025-07-02 06:41:17.099         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.099         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.099         >>> print(''.join(results), end="")
2025-07-02 06:41:17.099         - abcDefghiJkl
2025-07-02 06:41:17.099         + abcdefGhijkl
2025-07-02 06:41:17.099         """
2025-07-02 06:41:17.099
2025-07-02 06:41:17.099         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.099         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.100         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.100         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.100         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.100
2025-07-02 06:41:17.100         # search for the pair that matches best without being identical
2025-07-02 06:41:17.100         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.100         # on junk -- unless we have to)
2025-07-02 06:41:17.100         for j in range(blo, bhi):
2025-07-02 06:41:17.100             bj = b[j]
2025-07-02 06:41:17.100             cruncher.set_seq2(bj)
2025-07-02 06:41:17.100             for i in range(alo, ahi):
2025-07-02 06:41:17.100                 ai = a[i]
2025-07-02 06:41:17.100                 if ai == bj:
2025-07-02 06:41:17.100                     if eqi is None:
2025-07-02 06:41:17.100                         eqi, eqj = i, j
2025-07-02 06:41:17.100                     continue
2025-07-02 06:41:17.100                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.100                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.100                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.100                 # compares by a factor of 3.
2025-07-02 06:41:17.101                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.101                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.101                 # of the computation is cached by cruncher
2025-07-02 06:41:17.101                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.101                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.101                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.101                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.101         if best_ratio < cutoff:
2025-07-02 06:41:17.101             # no non-identical "pretty close" pair
2025-07-02 06:41:17.101             if eqi is None:
2025-07-02 06:41:17.101                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.101                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.101                 return
2025-07-02 06:41:17.101             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.101             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.101         else:
2025-07-02 06:41:17.101             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.101             eqi = None
2025-07-02 06:41:17.101
2025-07-02 06:41:17.101         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.102         # identical
2025-07-02 06:41:17.102
2025-07-02 06:41:17.102         # pump out diffs from before the synch point
2025-07-02 06:41:17.102         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.102
2025-07-02 06:41:17.102         # do intraline marking on the synch pair
2025-07-02 06:41:17.102         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.102         if eqi is None:
2025-07-02 06:41:17.102             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.102             atags = btags = ""
2025-07-02 06:41:17.102             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.102             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.102                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.102                 if tag == 'replace':
2025-07-02 06:41:17.102                     atags += '^' * la
2025-07-02 06:41:17.102                     btags += '^' * lb
2025-07-02 06:41:17.102                 elif tag == 'delete':
2025-07-02 06:41:17.102                     atags += '-' * la
2025-07-02 06:41:17.102                 elif tag == 'insert':
2025-07-02 06:41:17.102                     btags += '+' * lb
2025-07-02 06:41:17.103                 elif tag == 'equal':
2025-07-02 06:41:17.103                     atags += ' ' * la
2025-07-02 06:41:17.103                     btags += ' ' * lb
2025-07-02 06:41:17.103                 else:
2025-07-02 06:41:17.103                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.103             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.103         else:
2025-07-02 06:41:17.103             # the synch pair is identical
2025-07-02 06:41:17.103             yield '  ' + aelt
2025-07-02 06:41:17.103
2025-07-02 06:41:17.103         # pump out diffs from after the synch point
2025-07-02 06:41:17.103 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.103
2025-07-02 06:41:17.103 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.103 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.103
2025-07-02 06:41:17.103 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.103 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.103 alo = 171, ahi = 1101
2025-07-02 06:41:17.103 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.104 blo = 171, bhi = 1101
2025-07-02 06:41:17.104
2025-07-02 06:41:17.104     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.104         g = []
2025-07-02 06:41:17.104         if alo < ahi:
2025-07-02 06:41:17.104             if blo < bhi:
2025-07-02 06:41:17.104                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.104             else:
2025-07-02 06:41:17.104                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.104         elif blo < bhi:
2025-07-02 06:41:17.104             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.104
2025-07-02 06:41:17.104 >       yield from g
2025-07-02 06:41:17.104
2025-07-02 06:41:17.104 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.104 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.104
2025-07-02 06:41:17.104 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.104 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.104 alo = 171, ahi = 1101
2025-07-02 06:41:17.104 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.105 blo = 171, bhi = 1101
2025-07-02 06:41:17.105
2025-07-02 06:41:17.105     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.105         r"""
2025-07-02 06:41:17.105         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.105         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.105         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.105         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.105
2025-07-02 06:41:17.105         Example:
2025-07-02 06:41:17.105
2025-07-02 06:41:17.105         >>> d = Differ()
2025-07-02 06:41:17.105         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.105         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.105         >>> print(''.join(results), end="")
2025-07-02 06:41:17.105         - abcDefghiJkl
2025-07-02 06:41:17.105         + abcdefGhijkl
2025-07-02 06:41:17.105         """
2025-07-02 06:41:17.106
2025-07-02 06:41:17.106         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.106         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.106         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.106         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.106         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.106
2025-07-02 06:41:17.106         # search for the pair that matches best without being identical
2025-07-02 06:41:17.106         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.106         # on junk -- unless we have to)
2025-07-02 06:41:17.106         for j in range(blo, bhi):
2025-07-02 06:41:17.106             bj = b[j]
2025-07-02 06:41:17.106             cruncher.set_seq2(bj)
2025-07-02 06:41:17.106             for i in range(alo, ahi):
2025-07-02 06:41:17.106                 ai = a[i]
2025-07-02 06:41:17.106                 if ai == bj:
2025-07-02 06:41:17.106                     if eqi is None:
2025-07-02 06:41:17.106                         eqi, eqj = i, j
2025-07-02 06:41:17.106                     continue
2025-07-02 06:41:17.106                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.106                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.107                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.107                 # compares by a factor of 3.
2025-07-02 06:41:17.107                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.107                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.107                 # of the computation is cached by cruncher
2025-07-02 06:41:17.107                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.107                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.107                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.107                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.107         if best_ratio < cutoff:
2025-07-02 06:41:17.107             # no non-identical "pretty close" pair
2025-07-02 06:41:17.107             if eqi is None:
2025-07-02 06:41:17.107                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.107                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.107                 return
2025-07-02 06:41:17.107             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.107             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.107         else:
2025-07-02 06:41:17.107             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.108             eqi = None
2025-07-02 06:41:17.108
2025-07-02 06:41:17.108         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.108         # identical
2025-07-02 06:41:17.108
2025-07-02 06:41:17.108         # pump out diffs from before the synch point
2025-07-02 06:41:17.108         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.108
2025-07-02 06:41:17.108         # do intraline marking on the synch pair
2025-07-02 06:41:17.108         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.108         if eqi is None:
2025-07-02 06:41:17.108             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.108             atags = btags = ""
2025-07-02 06:41:17.108             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.108             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.108                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.108                 if tag == 'replace':
2025-07-02 06:41:17.108                     atags += '^' * la
2025-07-02 06:41:17.108                     btags += '^' * lb
2025-07-02 06:41:17.109                 elif tag == 'delete':
2025-07-02 06:41:17.109                     atags += '-' * la
2025-07-02 06:41:17.109                 elif tag == 'insert':
2025-07-02 06:41:17.109                     btags += '+' * lb
2025-07-02 06:41:17.109                 elif tag == 'equal':
2025-07-02 06:41:17.109                     atags += ' ' * la
2025-07-02 06:41:17.109                     btags += ' ' * lb
2025-07-02 06:41:17.109                 else:
2025-07-02 06:41:17.109                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.109             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.109         else:
2025-07-02 06:41:17.109             # the synch pair is identical
2025-07-02 06:41:17.109             yield '  ' + aelt
2025-07-02 06:41:17.109
2025-07-02 06:41:17.109         # pump out diffs from after the synch point
2025-07-02 06:41:17.109 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.109
2025-07-02 06:41:17.109 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.109 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.110
2025-07-02 06:41:17.110 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.110 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.110 alo = 172, ahi = 1101
2025-07-02 06:41:17.110 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.110 blo = 172, bhi = 1101
2025-07-02 06:41:17.110
2025-07-02 06:41:17.110     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.110         g = []
2025-07-02 06:41:17.110         if alo < ahi:
2025-07-02 06:41:17.110             if blo < bhi:
2025-07-02 06:41:17.110                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.110             else:
2025-07-02 06:41:17.110                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.110         elif blo < bhi:
2025-07-02 06:41:17.110             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.110
2025-07-02 06:41:17.110 >       yield from g
2025-07-02 06:41:17.110
2025-07-02 06:41:17.110 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.111 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.111
2025-07-02 06:41:17.111 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.111 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.111 alo = 172, ahi = 1101
2025-07-02 06:41:17.111 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.111 blo = 172, bhi = 1101
2025-07-02 06:41:17.111
2025-07-02 06:41:17.111     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.111         r"""
2025-07-02 06:41:17.111         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.111         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.111         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.111         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.111
2025-07-02 06:41:17.111         Example:
2025-07-02 06:41:17.111
2025-07-02 06:41:17.111         >>> d = Differ()
2025-07-02 06:41:17.111         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.111         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.112         >>> print(''.join(results), end="")
2025-07-02 06:41:17.112         - abcDefghiJkl
2025-07-02 06:41:17.112         + abcdefGhijkl
2025-07-02 06:41:17.112         """
2025-07-02 06:41:17.112
2025-07-02 06:41:17.112         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.112         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.112         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.112         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.112         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.112
2025-07-02 06:41:17.112         # search for the pair that matches best without being identical
2025-07-02 06:41:17.112         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.112         # on junk -- unless we have to)
2025-07-02 06:41:17.112         for j in range(blo, bhi):
2025-07-02 06:41:17.112             bj = b[j]
2025-07-02 06:41:17.112             cruncher.set_seq2(bj)
2025-07-02 06:41:17.112             for i in range(alo, ahi):
2025-07-02 06:41:17.113                 ai = a[i]
2025-07-02 06:41:17.113                 if ai == bj:
2025-07-02 06:41:17.113                     if eqi is None:
2025-07-02 06:41:17.113                         eqi, eqj = i, j
2025-07-02 06:41:17.113                     continue
2025-07-02 06:41:17.113                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.113                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.113                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.113                 # compares by a factor of 3.
2025-07-02 06:41:17.113                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.113                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.113                 # of the computation is cached by cruncher
2025-07-02 06:41:17.113                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.113                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.113                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.113                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.113         if best_ratio < cutoff:
2025-07-02 06:41:17.113             # no non-identical "pretty close" pair
2025-07-02 06:41:17.113             if eqi is None:
2025-07-02 06:41:17.113                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.113                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.114                 return
2025-07-02 06:41:17.114             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.114             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.114         else:
2025-07-02 06:41:17.114             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.114             eqi = None
2025-07-02 06:41:17.114
2025-07-02 06:41:17.114         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.114         # identical
2025-07-02 06:41:17.114
2025-07-02 06:41:17.114         # pump out diffs from before the synch point
2025-07-02 06:41:17.114         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.114
2025-07-02 06:41:17.114         # do intraline marking on the synch pair
2025-07-02 06:41:17.114         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.114         if eqi is None:
2025-07-02 06:41:17.114             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.114             atags = btags = ""
2025-07-02 06:41:17.114             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.115             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.115                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.115                 if tag == 'replace':
2025-07-02 06:41:17.115                     atags += '^' * la
2025-07-02 06:41:17.115                     btags += '^' * lb
2025-07-02 06:41:17.115                 elif tag == 'delete':
2025-07-02 06:41:17.115                     atags += '-' * la
2025-07-02 06:41:17.115                 elif tag == 'insert':
2025-07-02 06:41:17.115                     btags += '+' * lb
2025-07-02 06:41:17.115                 elif tag == 'equal':
2025-07-02 06:41:17.115                     atags += ' ' * la
2025-07-02 06:41:17.115                     btags += ' ' * lb
2025-07-02 06:41:17.115                 else:
2025-07-02 06:41:17.115                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.115             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.115         else:
2025-07-02 06:41:17.115             # the synch pair is identical
2025-07-02 06:41:17.115             yield '  ' + aelt
2025-07-02 06:41:17.115
2025-07-02 06:41:17.115         # pump out diffs from after the synch point
2025-07-02 06:41:17.116 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.116
2025-07-02 06:41:17.116 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.116 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.116
2025-07-02 06:41:17.116 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.116 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.116 alo = 173, ahi = 1101
2025-07-02 06:41:17.116 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.116 blo = 173, bhi = 1101
2025-07-02 06:41:17.116
2025-07-02 06:41:17.116     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.116         g = []
2025-07-02 06:41:17.116         if alo < ahi:
2025-07-02 06:41:17.116             if blo < bhi:
2025-07-02 06:41:17.116                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.116             else:
2025-07-02 06:41:17.116                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.116         elif blo < bhi:
2025-07-02 06:41:17.116             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.117
2025-07-02 06:41:17.117 >       yield from g
2025-07-02 06:41:17.117
2025-07-02 06:41:17.117 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.117 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.117
2025-07-02 06:41:17.117 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.117 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.117 alo = 173, ahi = 1101
2025-07-02 06:41:17.117 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.117 blo = 173, bhi = 1101
2025-07-02 06:41:17.117
2025-07-02 06:41:17.117     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.117         r"""
2025-07-02 06:41:17.117         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.117         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.117         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.117         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.117
2025-07-02 06:41:17.118         Example:
2025-07-02 06:41:17.118
2025-07-02 06:41:17.118         >>> d = Differ()
2025-07-02 06:41:17.118         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.118         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.118         >>> print(''.join(results), end="")
2025-07-02 06:41:17.118         - abcDefghiJkl
2025-07-02 06:41:17.118         + abcdefGhijkl
2025-07-02 06:41:17.118         """
2025-07-02 06:41:17.118
2025-07-02 06:41:17.118         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.118         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.118         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.118         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.118         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.118
2025-07-02 06:41:17.118         # search for the pair that matches best without being identical
2025-07-02 06:41:17.118         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.119         # on junk -- unless we have to)
2025-07-02 06:41:17.119         for j in range(blo, bhi):
2025-07-02 06:41:17.119             bj = b[j]
2025-07-02 06:41:17.119             cruncher.set_seq2(bj)
2025-07-02 06:41:17.119             for i in range(alo, ahi):
2025-07-02 06:41:17.119                 ai = a[i]
2025-07-02 06:41:17.119                 if ai == bj:
2025-07-02 06:41:17.119                     if eqi is None:
2025-07-02 06:41:17.119                         eqi, eqj = i, j
2025-07-02 06:41:17.119                     continue
2025-07-02 06:41:17.119                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.119                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.119                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.119                 # compares by a factor of 3.
2025-07-02 06:41:17.119                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.119                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.119                 # of the computation is cached by cruncher
2025-07-02 06:41:17.119                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.119                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.119                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.120                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.120         if best_ratio < cutoff:
2025-07-02 06:41:17.120             # no non-identical "pretty close" pair
2025-07-02 06:41:17.120             if eqi is None:
2025-07-02 06:41:17.120                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.120                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.120                 return
2025-07-02 06:41:17.120             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.120             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.120         else:
2025-07-02 06:41:17.120             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.120             eqi = None
2025-07-02 06:41:17.120
2025-07-02 06:41:17.120         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.120         # identical
2025-07-02 06:41:17.120
2025-07-02 06:41:17.120         # pump out diffs from before the synch point
2025-07-02 06:41:17.120         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.120
2025-07-02 06:41:17.120         # do intraline marking on the synch pair
2025-07-02 06:41:17.120         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.121         if eqi is None:
2025-07-02 06:41:17.121             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.121             atags = btags = ""
2025-07-02 06:41:17.121             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.121             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.121                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.121                 if tag == 'replace':
2025-07-02 06:41:17.121                     atags += '^' * la
2025-07-02 06:41:17.121                     btags += '^' * lb
2025-07-02 06:41:17.121                 elif tag == 'delete':
2025-07-02 06:41:17.121                     atags += '-' * la
2025-07-02 06:41:17.121                 elif tag == 'insert':
2025-07-02 06:41:17.121                     btags += '+' * lb
2025-07-02 06:41:17.121                 elif tag == 'equal':
2025-07-02 06:41:17.121                     atags += ' ' * la
2025-07-02 06:41:17.121                     btags += ' ' * lb
2025-07-02 06:41:17.121                 else:
2025-07-02 06:41:17.121                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.121             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.121         else:
2025-07-02 06:41:17.122             # the synch pair is identical
2025-07-02 06:41:17.122             yield '  ' + aelt
2025-07-02 06:41:17.122
2025-07-02 06:41:17.122         # pump out diffs from after the synch point
2025-07-02 06:41:17.122 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.122
2025-07-02 06:41:17.122 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.122 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.122
2025-07-02 06:41:17.122 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.122 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.122 alo = 174, ahi = 1101
2025-07-02 06:41:17.122 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.122 blo = 174, bhi = 1101
2025-07-02 06:41:17.122
2025-07-02 06:41:17.122     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.122         g = []
2025-07-02 06:41:17.122         if alo < ahi:
2025-07-02 06:41:17.122             if blo < bhi:
2025-07-02 06:41:17.122                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.123             else:
2025-07-02 06:41:17.123                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.123         elif blo < bhi:
2025-07-02 06:41:17.123             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.123
2025-07-02 06:41:17.123 >       yield from g
2025-07-02 06:41:17.123
2025-07-02 06:41:17.123 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.123 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.123
2025-07-02 06:41:17.123 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.123 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.123 alo = 174, ahi = 1101
2025-07-02 06:41:17.123 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.123 blo = 174, bhi = 1101
2025-07-02 06:41:17.123
2025-07-02 06:41:17.123     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.123         r"""
2025-07-02 06:41:17.123         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.123         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.124         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.124         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.124
2025-07-02 06:41:17.124         Example:
2025-07-02 06:41:17.124
2025-07-02 06:41:17.124         >>> d = Differ()
2025-07-02 06:41:17.124         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.124         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.124         >>> print(''.join(results), end="")
2025-07-02 06:41:17.124         - abcDefghiJkl
2025-07-02 06:41:17.124         + abcdefGhijkl
2025-07-02 06:41:17.124         """
2025-07-02 06:41:17.124
2025-07-02 06:41:17.124         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.124         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.124         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.124         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.125         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.125
2025-07-02 06:41:17.125         # search for the pair that matches best without being identical
2025-07-02 06:41:17.125         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.125         # on junk -- unless we have to)
2025-07-02 06:41:17.125         for j in range(blo, bhi):
2025-07-02 06:41:17.125             bj = b[j]
2025-07-02 06:41:17.125             cruncher.set_seq2(bj)
2025-07-02 06:41:17.125             for i in range(alo, ahi):
2025-07-02 06:41:17.125                 ai = a[i]
2025-07-02 06:41:17.125                 if ai == bj:
2025-07-02 06:41:17.125                     if eqi is None:
2025-07-02 06:41:17.125                         eqi, eqj = i, j
2025-07-02 06:41:17.125                     continue
2025-07-02 06:41:17.125                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.125                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.125                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.126                 # compares by a factor of 3.
2025-07-02 06:41:17.126                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.126                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.126                 # of the computation is cached by cruncher
2025-07-02 06:41:17.126                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.126                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.126                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.126                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.126         if best_ratio < cutoff:
2025-07-02 06:41:17.126             # no non-identical "pretty close" pair
2025-07-02 06:41:17.126             if eqi is None:
2025-07-02 06:41:17.126                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.126                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.126                 return
2025-07-02 06:41:17.126             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.126             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.126         else:
2025-07-02 06:41:17.126             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.126             eqi = None
2025-07-02 06:41:17.127
2025-07-02 06:41:17.127         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.127         # identical
2025-07-02 06:41:17.127
2025-07-02 06:41:17.127         # pump out diffs from before the synch point
2025-07-02 06:41:17.127         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.127
2025-07-02 06:41:17.127         # do intraline marking on the synch pair
2025-07-02 06:41:17.127         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.127         if eqi is None:
2025-07-02 06:41:17.127             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.127             atags = btags = ""
2025-07-02 06:41:17.127             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.127             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.127                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.127                 if tag == 'replace':
2025-07-02 06:41:17.127                     atags += '^' * la
2025-07-02 06:41:17.127                     btags += '^' * lb
2025-07-02 06:41:17.127                 elif tag == 'delete':
2025-07-02 06:41:17.128                     atags += '-' * la
2025-07-02 06:41:17.128                 elif tag == 'insert':
2025-07-02 06:41:17.128                     btags += '+' * lb
2025-07-02 06:41:17.128                 elif tag == 'equal':
2025-07-02 06:41:17.128                     atags += ' ' * la
2025-07-02 06:41:17.128                     btags += ' ' * lb
2025-07-02 06:41:17.128                 else:
2025-07-02 06:41:17.128                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.128             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.128         else:
2025-07-02 06:41:17.128             # the synch pair is identical
2025-07-02 06:41:17.128             yield '  ' + aelt
2025-07-02 06:41:17.128
2025-07-02 06:41:17.128         # pump out diffs from after the synch point
2025-07-02 06:41:17.128 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.128
2025-07-02 06:41:17.128 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.128 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.128
2025-07-02 06:41:17.128 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.129 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.129 alo = 175, ahi = 1101
2025-07-02 06:41:17.129 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.129 blo = 175, bhi = 1101
2025-07-02 06:41:17.129
2025-07-02 06:41:17.129     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.129         g = []
2025-07-02 06:41:17.129         if alo < ahi:
2025-07-02 06:41:17.129             if blo < bhi:
2025-07-02 06:41:17.129                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.129             else:
2025-07-02 06:41:17.129                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.129         elif blo < bhi:
2025-07-02 06:41:17.129             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.129
2025-07-02 06:41:17.129 >       yield from g
2025-07-02 06:41:17.129
2025-07-02 06:41:17.129 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.129 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.129
2025-07-02 06:41:17.130 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.130 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.130 alo = 175, ahi = 1101
2025-07-02 06:41:17.130 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.130 blo = 175, bhi = 1101
2025-07-02 06:41:17.130
2025-07-02 06:41:17.130     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.130         r"""
2025-07-02 06:41:17.130         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.130         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.130         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.130         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.130
2025-07-02 06:41:17.130         Example:
2025-07-02 06:41:17.130
2025-07-02 06:41:17.130         >>> d = Differ()
2025-07-02 06:41:17.130         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.130         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.130         >>> print(''.join(results), end="")
2025-07-02 06:41:17.131         - abcDefghiJkl
2025-07-02 06:41:17.131         + abcdefGhijkl
2025-07-02 06:41:17.131         """
2025-07-02 06:41:17.131
2025-07-02 06:41:17.131         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.131         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.131         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.131         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.131         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.131
2025-07-02 06:41:17.131         # search for the pair that matches best without being identical
2025-07-02 06:41:17.131         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.131         # on junk -- unless we have to)
2025-07-02 06:41:17.131         for j in range(blo, bhi):
2025-07-02 06:41:17.131             bj = b[j]
2025-07-02 06:41:17.131             cruncher.set_seq2(bj)
2025-07-02 06:41:17.131             for i in range(alo, ahi):
2025-07-02 06:41:17.131                 ai = a[i]
2025-07-02 06:41:17.132                 if ai == bj:
2025-07-02 06:41:17.132                     if eqi is None:
2025-07-02 06:41:17.132                         eqi, eqj = i, j
2025-07-02 06:41:17.132                     continue
2025-07-02 06:41:17.132                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.132                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.132                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.132                 # compares by a factor of 3.
2025-07-02 06:41:17.132                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.132                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.132                 # of the computation is cached by cruncher
2025-07-02 06:41:17.132                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.132                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.132                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.132                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.132         if best_ratio < cutoff:
2025-07-02 06:41:17.132             # no non-identical "pretty close" pair
2025-07-02 06:41:17.132             if eqi is None:
2025-07-02 06:41:17.132                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.132                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.133                 return
2025-07-02 06:41:17.133             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.133             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.133         else:
2025-07-02 06:41:17.133             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.133             eqi = None
2025-07-02 06:41:17.133
2025-07-02 06:41:17.133         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.133         # identical
2025-07-02 06:41:17.133
2025-07-02 06:41:17.133         # pump out diffs from before the synch point
2025-07-02 06:41:17.133         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.133
2025-07-02 06:41:17.133         # do intraline marking on the synch pair
2025-07-02 06:41:17.133         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.133         if eqi is None:
2025-07-02 06:41:17.133             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.133             atags = btags = ""
2025-07-02 06:41:17.133             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.133             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.134                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.134                 if tag == 'replace':
2025-07-02 06:41:17.134                     atags += '^' * la
2025-07-02 06:41:17.134                     btags += '^' * lb
2025-07-02 06:41:17.134                 elif tag == 'delete':
2025-07-02 06:41:17.134                     atags += '-' * la
2025-07-02 06:41:17.134                 elif tag == 'insert':
2025-07-02 06:41:17.134                     btags += '+' * lb
2025-07-02 06:41:17.134                 elif tag == 'equal':
2025-07-02 06:41:17.134                     atags += ' ' * la
2025-07-02 06:41:17.134                     btags += ' ' * lb
2025-07-02 06:41:17.134                 else:
2025-07-02 06:41:17.134                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.134             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.134         else:
2025-07-02 06:41:17.134             # the synch pair is identical
2025-07-02 06:41:17.134             yield '  ' + aelt
2025-07-02 06:41:17.134
2025-07-02 06:41:17.135         # pump out diffs from after the synch point
2025-07-02 06:41:17.135 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.135
2025-07-02 06:41:17.135 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.135 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.135
2025-07-02 06:41:17.135 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.135 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.135 alo = 176, ahi = 1101
2025-07-02 06:41:17.135 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.135 blo = 176, bhi = 1101
2025-07-02 06:41:17.135
2025-07-02 06:41:17.135     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.135         g = []
2025-07-02 06:41:17.135         if alo < ahi:
2025-07-02 06:41:17.135             if blo < bhi:
2025-07-02 06:41:17.135                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.136             else:
2025-07-02 06:41:17.136                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.136         elif blo < bhi:
2025-07-02 06:41:17.136             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.136
2025-07-02 06:41:17.136 >       yield from g
2025-07-02 06:41:17.136
2025-07-02 06:41:17.136 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.136 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.136
2025-07-02 06:41:17.136 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.136 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.136 alo = 176, ahi = 1101
2025-07-02 06:41:17.136 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.136 blo = 176, bhi = 1101
2025-07-02 06:41:17.136
2025-07-02 06:41:17.136     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.136         r"""
2025-07-02 06:41:17.136         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.137         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.137         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.137         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.137
2025-07-02 06:41:17.137         Example:
2025-07-02 06:41:17.137
2025-07-02 06:41:17.137         >>> d = Differ()
2025-07-02 06:41:17.137         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.137         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.137         >>> print(''.join(results), end="")
2025-07-02 06:41:17.137         - abcDefghiJkl
2025-07-02 06:41:17.137         + abcdefGhijkl
2025-07-02 06:41:17.137         """
2025-07-02 06:41:17.137
2025-07-02 06:41:17.137         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.137         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.137         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.138         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.138         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.138
2025-07-02 06:41:17.138         # search for the pair that matches best without being identical
2025-07-02 06:41:17.138         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.138         # on junk -- unless we have to)
2025-07-02 06:41:17.138         for j in range(blo, bhi):
2025-07-02 06:41:17.138             bj = b[j]
2025-07-02 06:41:17.138             cruncher.set_seq2(bj)
2025-07-02 06:41:17.138             for i in range(alo, ahi):
2025-07-02 06:41:17.138                 ai = a[i]
2025-07-02 06:41:17.138                 if ai == bj:
2025-07-02 06:41:17.138                     if eqi is None:
2025-07-02 06:41:17.138                         eqi, eqj = i, j
2025-07-02 06:41:17.138                     continue
2025-07-02 06:41:17.138                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.138                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.138                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.138                 # compares by a factor of 3.
2025-07-02 06:41:17.138                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.139                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.139                 # of the computation is cached by cruncher
2025-07-02 06:41:17.139                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.139                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.139                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.139                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.139         if best_ratio < cutoff:
2025-07-02 06:41:17.139             # no non-identical "pretty close" pair
2025-07-02 06:41:17.139             if eqi is None:
2025-07-02 06:41:17.139                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.139                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.139                 return
2025-07-02 06:41:17.139             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.139             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.139         else:
2025-07-02 06:41:17.139             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.139             eqi = None
2025-07-02 06:41:17.139
2025-07-02 06:41:17.140         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.140         # identical
2025-07-02 06:41:17.140
2025-07-02 06:41:17.140         # pump out diffs from before the synch point
2025-07-02 06:41:17.140         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.140
2025-07-02 06:41:17.140         # do intraline marking on the synch pair
2025-07-02 06:41:17.140         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.140         if eqi is None:
2025-07-02 06:41:17.140             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.140             atags = btags = ""
2025-07-02 06:41:17.140             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.140             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.140                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.140                 if tag == 'replace':
2025-07-02 06:41:17.140                     atags += '^' * la
2025-07-02 06:41:17.140                     btags += '^' * lb
2025-07-02 06:41:17.140                 elif tag == 'delete':
2025-07-02 06:41:17.140                     atags += '-' * la
2025-07-02 06:41:17.141                 elif tag == 'insert':
2025-07-02 06:41:17.141                     btags += '+' * lb
2025-07-02 06:41:17.141                 elif tag == 'equal':
2025-07-02 06:41:17.141                     atags += ' ' * la
2025-07-02 06:41:17.141                     btags += ' ' * lb
2025-07-02 06:41:17.141                 else:
2025-07-02 06:41:17.141                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.141             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.141         else:
2025-07-02 06:41:17.141             # the synch pair is identical
2025-07-02 06:41:17.141             yield '  ' + aelt
2025-07-02 06:41:17.141
2025-07-02 06:41:17.141         # pump out diffs from after the synch point
2025-07-02 06:41:17.141 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.141
2025-07-02 06:41:17.141 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.141 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.141
2025-07-02 06:41:17.141 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.141 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.142 alo = 177, ahi = 1101
2025-07-02 06:41:17.142 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.142 blo = 177, bhi = 1101
2025-07-02 06:41:17.142
2025-07-02 06:41:17.142     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.142         g = []
2025-07-02 06:41:17.142         if alo < ahi:
2025-07-02 06:41:17.142             if blo < bhi:
2025-07-02 06:41:17.142                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.142             else:
2025-07-02 06:41:17.142                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.142         elif blo < bhi:
2025-07-02 06:41:17.142             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.142
2025-07-02 06:41:17.142 >       yield from g
2025-07-02 06:41:17.142
2025-07-02 06:41:17.142 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.142 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.142
2025-07-02 06:41:17.142 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.143 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.143 alo = 177, ahi = 1101
2025-07-02 06:41:17.143 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.143 blo = 177, bhi = 1101
2025-07-02 06:41:17.143
2025-07-02 06:41:17.143     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.143         r"""
2025-07-02 06:41:17.143         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.143         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.143         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.143         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.143
2025-07-02 06:41:17.143         Example:
2025-07-02 06:41:17.143
2025-07-02 06:41:17.143         >>> d = Differ()
2025-07-02 06:41:17.143         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.143         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.143         >>> print(''.join(results), end="")
2025-07-02 06:41:17.144         - abcDefghiJkl
2025-07-02 06:41:17.144         + abcdefGhijkl
2025-07-02 06:41:17.144         """
2025-07-02 06:41:17.144
2025-07-02 06:41:17.144         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.144         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.144         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.144         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.144         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.144
2025-07-02 06:41:17.144         # search for the pair that matches best without being identical
2025-07-02 06:41:17.144         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.144         # on junk -- unless we have to)
2025-07-02 06:41:17.144         for j in range(blo, bhi):
2025-07-02 06:41:17.144             bj = b[j]
2025-07-02 06:41:17.144             cruncher.set_seq2(bj)
2025-07-02 06:41:17.144             for i in range(alo, ahi):
2025-07-02 06:41:17.145                 ai = a[i]
2025-07-02 06:41:17.145                 if ai == bj:
2025-07-02 06:41:17.145                     if eqi is None:
2025-07-02 06:41:17.145                         eqi, eqj = i, j
2025-07-02 06:41:17.145                     continue
2025-07-02 06:41:17.145                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.145                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.145                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.145                 # compares by a factor of 3.
2025-07-02 06:41:17.145                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.145                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.145                 # of the computation is cached by cruncher
2025-07-02 06:41:17.145                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.145                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.145                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.145                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.145         if best_ratio < cutoff:
2025-07-02 06:41:17.145             # no non-identical "pretty close" pair
2025-07-02 06:41:17.145             if eqi is None:
2025-07-02 06:41:17.146                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.146                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.146                 return
2025-07-02 06:41:17.146             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.146             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.146         else:
2025-07-02 06:41:17.146             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.146             eqi = None
2025-07-02 06:41:17.146
2025-07-02 06:41:17.146         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.146         # identical
2025-07-02 06:41:17.146
2025-07-02 06:41:17.146         # pump out diffs from before the synch point
2025-07-02 06:41:17.146         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.146
2025-07-02 06:41:17.146         # do intraline marking on the synch pair
2025-07-02 06:41:17.146         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.146         if eqi is None:
2025-07-02 06:41:17.146             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.146             atags = btags = ""
2025-07-02 06:41:17.146             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.147             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.147                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.147                 if tag == 'replace':
2025-07-02 06:41:17.147                     atags += '^' * la
2025-07-02 06:41:17.147                     btags += '^' * lb
2025-07-02 06:41:17.147                 elif tag == 'delete':
2025-07-02 06:41:17.147                     atags += '-' * la
2025-07-02 06:41:17.147                 elif tag == 'insert':
2025-07-02 06:41:17.147                     btags += '+' * lb
2025-07-02 06:41:17.147                 elif tag == 'equal':
2025-07-02 06:41:17.147                     atags += ' ' * la
2025-07-02 06:41:17.147                     btags += ' ' * lb
2025-07-02 06:41:17.147                 else:
2025-07-02 06:41:17.147                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.147             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.147         else:
2025-07-02 06:41:17.147             # the synch pair is identical
2025-07-02 06:41:17.147             yield '  ' + aelt
2025-07-02 06:41:17.147
2025-07-02 06:41:17.147         # pump out diffs from after the synch point
2025-07-02 06:41:17.148 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.148
2025-07-02 06:41:17.148 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.148 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.148
2025-07-02 06:41:17.148 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.148 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.148 alo = 180, ahi = 1101
2025-07-02 06:41:17.148 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.148 blo = 180, bhi = 1101
2025-07-02 06:41:17.148
2025-07-02 06:41:17.148     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.148         g = []
2025-07-02 06:41:17.148         if alo < ahi:
2025-07-02 06:41:17.148             if blo < bhi:
2025-07-02 06:41:17.148                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.148             else:
2025-07-02 06:41:17.148                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.148         elif blo < bhi:
2025-07-02 06:41:17.148             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.149
2025-07-02 06:41:17.149 >       yield from g
2025-07-02 06:41:17.149
2025-07-02 06:41:17.149 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.149 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.149
2025-07-02 06:41:17.149 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.149 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.149 alo = 180, ahi = 1101
2025-07-02 06:41:17.149 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.149 blo = 180, bhi = 1101
2025-07-02 06:41:17.149
2025-07-02 06:41:17.149     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.149         r"""
2025-07-02 06:41:17.149         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.149         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.149         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.149         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.149
2025-07-02 06:41:17.150         Example:
2025-07-02 06:41:17.150
2025-07-02 06:41:17.150         >>> d = Differ()
2025-07-02 06:41:17.150         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.150         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.150         >>> print(''.join(results), end="")
2025-07-02 06:41:17.150         - abcDefghiJkl
2025-07-02 06:41:17.150         + abcdefGhijkl
2025-07-02 06:41:17.150         """
2025-07-02 06:41:17.150
2025-07-02 06:41:17.150         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.150         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.150         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.150         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.150         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.150
2025-07-02 06:41:17.150         # search for the pair that matches best without being identical
2025-07-02 06:41:17.150         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.151         # on junk -- unless we have to)
2025-07-02 06:41:17.151         for j in range(blo, bhi):
2025-07-02 06:41:17.151             bj = b[j]
2025-07-02 06:41:17.151             cruncher.set_seq2(bj)
2025-07-02 06:41:17.151             for i in range(alo, ahi):
2025-07-02 06:41:17.151                 ai = a[i]
2025-07-02 06:41:17.151                 if ai == bj:
2025-07-02 06:41:17.151                     if eqi is None:
2025-07-02 06:41:17.151                         eqi, eqj = i, j
2025-07-02 06:41:17.151                     continue
2025-07-02 06:41:17.151                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.151                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.151                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.151                 # compares by a factor of 3.
2025-07-02 06:41:17.151                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.151                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.151                 # of the computation is cached by cruncher
2025-07-02 06:41:17.151                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.151                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.151                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.152                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.152         if best_ratio < cutoff:
2025-07-02 06:41:17.152             # no non-identical "pretty close" pair
2025-07-02 06:41:17.152             if eqi is None:
2025-07-02 06:41:17.152                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.152                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.152                 return
2025-07-02 06:41:17.152             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.152             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.152         else:
2025-07-02 06:41:17.152             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.152             eqi = None
2025-07-02 06:41:17.152
2025-07-02 06:41:17.152         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.152         # identical
2025-07-02 06:41:17.152
2025-07-02 06:41:17.152         # pump out diffs from before the synch point
2025-07-02 06:41:17.152         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.153
2025-07-02 06:41:17.153         # do intraline marking on the synch pair
2025-07-02 06:41:17.153         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.153         if eqi is None:
2025-07-02 06:41:17.153             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.153             atags = btags = ""
2025-07-02 06:41:17.153             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.153             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.153                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.153                 if tag == 'replace':
2025-07-02 06:41:17.153                     atags += '^' * la
2025-07-02 06:41:17.153                     btags += '^' * lb
2025-07-02 06:41:17.153                 elif tag == 'delete':
2025-07-02 06:41:17.153                     atags += '-' * la
2025-07-02 06:41:17.153                 elif tag == 'insert':
2025-07-02 06:41:17.153                     btags += '+' * lb
2025-07-02 06:41:17.153                 elif tag == 'equal':
2025-07-02 06:41:17.153                     atags += ' ' * la
2025-07-02 06:41:17.153                     btags += ' ' * lb
2025-07-02 06:41:17.154                 else:
2025-07-02 06:41:17.154                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.154             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.154         else:
2025-07-02 06:41:17.154             # the synch pair is identical
2025-07-02 06:41:17.154             yield '  ' + aelt
2025-07-02 06:41:17.154
2025-07-02 06:41:17.154         # pump out diffs from after the synch point
2025-07-02 06:41:17.154 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.154
2025-07-02 06:41:17.154 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.154 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.154
2025-07-02 06:41:17.154 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.154 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.154 alo = 181, ahi = 1101
2025-07-02 06:41:17.154 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.154 blo = 181, bhi = 1101
2025-07-02 06:41:17.154
2025-07-02 06:41:17.154     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.155         g = []
2025-07-02 06:41:17.155         if alo < ahi:
2025-07-02 06:41:17.155             if blo < bhi:
2025-07-02 06:41:17.155                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.155             else:
2025-07-02 06:41:17.155                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.155         elif blo < bhi:
2025-07-02 06:41:17.155             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.155
2025-07-02 06:41:17.155 >       yield from g
2025-07-02 06:41:17.155
2025-07-02 06:41:17.155 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.155 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.155
2025-07-02 06:41:17.155 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.155 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.155 alo = 181, ahi = 1101
2025-07-02 06:41:17.155 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.156 blo = 181, bhi = 1101
2025-07-02 06:41:17.156
2025-07-02 06:41:17.156     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.156         r"""
2025-07-02 06:41:17.156         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.156         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.156         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.156         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.156
2025-07-02 06:41:17.156         Example:
2025-07-02 06:41:17.156
2025-07-02 06:41:17.156         >>> d = Differ()
2025-07-02 06:41:17.156         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.156         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.156         >>> print(''.join(results), end="")
2025-07-02 06:41:17.156         - abcDefghiJkl
2025-07-02 06:41:17.156         + abcdefGhijkl
2025-07-02 06:41:17.156         """
2025-07-02 06:41:17.157
2025-07-02 06:41:17.157         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.157         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.157         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.157         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.157         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.157
2025-07-02 06:41:17.157         # search for the pair that matches best without being identical
2025-07-02 06:41:17.157         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.157         # on junk -- unless we have to)
2025-07-02 06:41:17.157         for j in range(blo, bhi):
2025-07-02 06:41:17.157             bj = b[j]
2025-07-02 06:41:17.157             cruncher.set_seq2(bj)
2025-07-02 06:41:17.157             for i in range(alo, ahi):
2025-07-02 06:41:17.157                 ai = a[i]
2025-07-02 06:41:17.157                 if ai == bj:
2025-07-02 06:41:17.157                     if eqi is None:
2025-07-02 06:41:17.157                         eqi, eqj = i, j
2025-07-02 06:41:17.157                     continue
2025-07-02 06:41:17.157                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.157                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.158                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.158                 # compares by a factor of 3.
2025-07-02 06:41:17.158                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.158                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.158                 # of the computation is cached by cruncher
2025-07-02 06:41:17.158                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.158                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.158                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.158                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.158         if best_ratio < cutoff:
2025-07-02 06:41:17.158             # no non-identical "pretty close" pair
2025-07-02 06:41:17.158             if eqi is None:
2025-07-02 06:41:17.158                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.158                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.158                 return
2025-07-02 06:41:17.158             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.158             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.158         else:
2025-07-02 06:41:17.158             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.158             eqi = None
2025-07-02 06:41:17.159
2025-07-02 06:41:17.159         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.159         # identical
2025-07-02 06:41:17.159
2025-07-02 06:41:17.159         # pump out diffs from before the synch point
2025-07-02 06:41:17.159         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.159
2025-07-02 06:41:17.159         # do intraline marking on the synch pair
2025-07-02 06:41:17.159         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.159         if eqi is None:
2025-07-02 06:41:17.159             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.159             atags = btags = ""
2025-07-02 06:41:17.159             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.159             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.159                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.159                 if tag == 'replace':
2025-07-02 06:41:17.159                     atags += '^' * la
2025-07-02 06:41:17.159                     btags += '^' * lb
2025-07-02 06:41:17.159                 elif tag == 'delete':
2025-07-02 06:41:17.159                     atags += '-' * la
2025-07-02 06:41:17.159                 elif tag == 'insert':
2025-07-02 06:41:17.160                     btags += '+' * lb
2025-07-02 06:41:17.160                 elif tag == 'equal':
2025-07-02 06:41:17.160                     atags += ' ' * la
2025-07-02 06:41:17.160                     btags += ' ' * lb
2025-07-02 06:41:17.160                 else:
2025-07-02 06:41:17.160                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.160             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.160         else:
2025-07-02 06:41:17.160             # the synch pair is identical
2025-07-02 06:41:17.160             yield '  ' + aelt
2025-07-02 06:41:17.160
2025-07-02 06:41:17.160         # pump out diffs from after the synch point
2025-07-02 06:41:17.160 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.160
2025-07-02 06:41:17.160 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.160 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.160
2025-07-02 06:41:17.160 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.160 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.160 alo = 182, ahi = 1101
2025-07-02 06:41:17.161 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.161 blo = 182, bhi = 1101
2025-07-02 06:41:17.161
2025-07-02 06:41:17.161     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.161         g = []
2025-07-02 06:41:17.161         if alo < ahi:
2025-07-02 06:41:17.161             if blo < bhi:
2025-07-02 06:41:17.161                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.161             else:
2025-07-02 06:41:17.161                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.161         elif blo < bhi:
2025-07-02 06:41:17.161             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.161
2025-07-02 06:41:17.161 >       yield from g
2025-07-02 06:41:17.161
2025-07-02 06:41:17.161 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.161 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.161
2025-07-02 06:41:17.161 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.162 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.162 alo = 182, ahi = 1101
2025-07-02 06:41:17.162 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.162 blo = 182, bhi = 1101
2025-07-02 06:41:17.162
2025-07-02 06:41:17.162     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.162         r"""
2025-07-02 06:41:17.162         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.162         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.162         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.162         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.162
2025-07-02 06:41:17.162         Example:
2025-07-02 06:41:17.162
2025-07-02 06:41:17.162         >>> d = Differ()
2025-07-02 06:41:17.162         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.162         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.162         >>> print(''.join(results), end="")
2025-07-02 06:41:17.162         - abcDefghiJkl
2025-07-02 06:41:17.163         + abcdefGhijkl
2025-07-02 06:41:17.163         """
2025-07-02 06:41:17.163
2025-07-02 06:41:17.163         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.163         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.163         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.163         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.163         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.163
2025-07-02 06:41:17.163         # search for the pair that matches best without being identical
2025-07-02 06:41:17.163         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.163         # on junk -- unless we have to)
2025-07-02 06:41:17.163         for j in range(blo, bhi):
2025-07-02 06:41:17.163             bj = b[j]
2025-07-02 06:41:17.163             cruncher.set_seq2(bj)
2025-07-02 06:41:17.163             for i in range(alo, ahi):
2025-07-02 06:41:17.163                 ai = a[i]
2025-07-02 06:41:17.163                 if ai == bj:
2025-07-02 06:41:17.163                     if eqi is None:
2025-07-02 06:41:17.164                         eqi, eqj = i, j
2025-07-02 06:41:17.164                     continue
2025-07-02 06:41:17.164                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.164                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.164                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.164                 # compares by a factor of 3.
2025-07-02 06:41:17.164                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.164                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.164                 # of the computation is cached by cruncher
2025-07-02 06:41:17.164                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.164                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.164                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.164                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.164         if best_ratio < cutoff:
2025-07-02 06:41:17.164             # no non-identical "pretty close" pair
2025-07-02 06:41:17.164             if eqi is None:
2025-07-02 06:41:17.164                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.164                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.164                 return
2025-07-02 06:41:17.164             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.165             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.165         else:
2025-07-02 06:41:17.165             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.165             eqi = None
2025-07-02 06:41:17.165
2025-07-02 06:41:17.165         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.165         # identical
2025-07-02 06:41:17.165
2025-07-02 06:41:17.165         # pump out diffs from before the synch point
2025-07-02 06:41:17.165         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.165
2025-07-02 06:41:17.165         # do intraline marking on the synch pair
2025-07-02 06:41:17.165         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.165         if eqi is None:
2025-07-02 06:41:17.165             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.165             atags = btags = ""
2025-07-02 06:41:17.165             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.165             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.165                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.165                 if tag == 'replace':
2025-07-02 06:41:17.166                     atags += '^' * la
2025-07-02 06:41:17.166                     btags += '^' * lb
2025-07-02 06:41:17.166                 elif tag == 'delete':
2025-07-02 06:41:17.166                     atags += '-' * la
2025-07-02 06:41:17.166                 elif tag == 'insert':
2025-07-02 06:41:17.166                     btags += '+' * lb
2025-07-02 06:41:17.166                 elif tag == 'equal':
2025-07-02 06:41:17.166                     atags += ' ' * la
2025-07-02 06:41:17.166                     btags += ' ' * lb
2025-07-02 06:41:17.166                 else:
2025-07-02 06:41:17.166                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.166             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.166         else:
2025-07-02 06:41:17.166             # the synch pair is identical
2025-07-02 06:41:17.166             yield '  ' + aelt
2025-07-02 06:41:17.166
2025-07-02 06:41:17.166         # pump out diffs from after the synch point
2025-07-02 06:41:17.166 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.166
2025-07-02 06:41:17.166 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.166 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.167
2025-07-02 06:41:17.167 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.167 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.167 alo = 183, ahi = 1101
2025-07-02 06:41:17.167 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.167 blo = 183, bhi = 1101
2025-07-02 06:41:17.167
2025-07-02 06:41:17.167     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.167         g = []
2025-07-02 06:41:17.167         if alo < ahi:
2025-07-02 06:41:17.167             if blo < bhi:
2025-07-02 06:41:17.167                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.167             else:
2025-07-02 06:41:17.167                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.167         elif blo < bhi:
2025-07-02 06:41:17.167             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.167
2025-07-02 06:41:17.167 >       yield from g
2025-07-02 06:41:17.167
2025-07-02 06:41:17.167 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.168 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.168
2025-07-02 06:41:17.168 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.168 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.168 alo = 183, ahi = 1101
2025-07-02 06:41:17.168 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.168 blo = 183, bhi = 1101
2025-07-02 06:41:17.168
2025-07-02 06:41:17.168     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.168         r"""
2025-07-02 06:41:17.168         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.168         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.168         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.168         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.168
2025-07-02 06:41:17.168         Example:
2025-07-02 06:41:17.168
2025-07-02 06:41:17.168         >>> d = Differ()
2025-07-02 06:41:17.168         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.168         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.169         >>> print(''.join(results), end="")
2025-07-02 06:41:17.169         - abcDefghiJkl
2025-07-02 06:41:17.169         + abcdefGhijkl
2025-07-02 06:41:17.169         """
2025-07-02 06:41:17.169
2025-07-02 06:41:17.169         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.169         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.169         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.169         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.169         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.169
2025-07-02 06:41:17.169         # search for the pair that matches best without being identical
2025-07-02 06:41:17.169         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.169         # on junk -- unless we have to)
2025-07-02 06:41:17.169         for j in range(blo, bhi):
2025-07-02 06:41:17.169             bj = b[j]
2025-07-02 06:41:17.169             cruncher.set_seq2(bj)
2025-07-02 06:41:17.169             for i in range(alo, ahi):
2025-07-02 06:41:17.170                 ai = a[i]
2025-07-02 06:41:17.170                 if ai == bj:
2025-07-02 06:41:17.170                     if eqi is None:
2025-07-02 06:41:17.170                         eqi, eqj = i, j
2025-07-02 06:41:17.170                     continue
2025-07-02 06:41:17.170                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.170                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.170                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.170                 # compares by a factor of 3.
2025-07-02 06:41:17.170                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.170                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.170                 # of the computation is cached by cruncher
2025-07-02 06:41:17.170                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.170                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.170                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.170                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.170         if best_ratio < cutoff:
2025-07-02 06:41:17.170             # no non-identical "pretty close" pair
2025-07-02 06:41:17.170             if eqi is None:
2025-07-02 06:41:17.171                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.171                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.171                 return
2025-07-02 06:41:17.171             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.171             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.171         else:
2025-07-02 06:41:17.171             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.171             eqi = None
2025-07-02 06:41:17.171
2025-07-02 06:41:17.171         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.171         # identical
2025-07-02 06:41:17.171
2025-07-02 06:41:17.171         # pump out diffs from before the synch point
2025-07-02 06:41:17.171         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.171
2025-07-02 06:41:17.171         # do intraline marking on the synch pair
2025-07-02 06:41:17.171         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.171         if eqi is None:
2025-07-02 06:41:17.171             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.172             atags = btags = ""
2025-07-02 06:41:17.172             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.172             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.172                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.172                 if tag == 'replace':
2025-07-02 06:41:17.172                     atags += '^' * la
2025-07-02 06:41:17.172                     btags += '^' * lb
2025-07-02 06:41:17.172                 elif tag == 'delete':
2025-07-02 06:41:17.172                     atags += '-' * la
2025-07-02 06:41:17.172                 elif tag == 'insert':
2025-07-02 06:41:17.172                     btags += '+' * lb
2025-07-02 06:41:17.172                 elif tag == 'equal':
2025-07-02 06:41:17.172                     atags += ' ' * la
2025-07-02 06:41:17.172                     btags += ' ' * lb
2025-07-02 06:41:17.172                 else:
2025-07-02 06:41:17.172                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.172             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.172         else:
2025-07-02 06:41:17.172             # the synch pair is identical
2025-07-02 06:41:17.172             yield '  ' + aelt
2025-07-02 06:41:17.173
2025-07-02 06:41:17.173         # pump out diffs from after the synch point
2025-07-02 06:41:17.173 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.173
2025-07-02 06:41:17.173 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.173 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.173
2025-07-02 06:41:17.173 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.173 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.173 alo = 184, ahi = 1101
2025-07-02 06:41:17.173 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.173 blo = 184, bhi = 1101
2025-07-02 06:41:17.173
2025-07-02 06:41:17.173     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.173         g = []
2025-07-02 06:41:17.173         if alo < ahi:
2025-07-02 06:41:17.173             if blo < bhi:
2025-07-02 06:41:17.173                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.173             else:
2025-07-02 06:41:17.173                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.173         elif blo < bhi:
2025-07-02 06:41:17.174             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.174
2025-07-02 06:41:17.174 >       yield from g
2025-07-02 06:41:17.174
2025-07-02 06:41:17.174 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.174 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.174
2025-07-02 06:41:17.174 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.174 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.174 alo = 184, ahi = 1101
2025-07-02 06:41:17.174 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.174 blo = 184, bhi = 1101
2025-07-02 06:41:17.174
2025-07-02 06:41:17.174     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.174         r"""
2025-07-02 06:41:17.174         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.174         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.174         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.174         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.174
2025-07-02 06:41:17.175         Example:
2025-07-02 06:41:17.175
2025-07-02 06:41:17.175         >>> d = Differ()
2025-07-02 06:41:17.175         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.175         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.175         >>> print(''.join(results), end="")
2025-07-02 06:41:17.175         - abcDefghiJkl
2025-07-02 06:41:17.175         + abcdefGhijkl
2025-07-02 06:41:17.175         """
2025-07-02 06:41:17.175
2025-07-02 06:41:17.175         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.175         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.175         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.175         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.175         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.175
2025-07-02 06:41:17.175         # search for the pair that matches best without being identical
2025-07-02 06:41:17.175         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.176         # on junk -- unless we have to)
2025-07-02 06:41:17.176         for j in range(blo, bhi):
2025-07-02 06:41:17.176             bj = b[j]
2025-07-02 06:41:17.176             cruncher.set_seq2(bj)
2025-07-02 06:41:17.176             for i in range(alo, ahi):
2025-07-02 06:41:17.176                 ai = a[i]
2025-07-02 06:41:17.176                 if ai == bj:
2025-07-02 06:41:17.176                     if eqi is None:
2025-07-02 06:41:17.176                         eqi, eqj = i, j
2025-07-02 06:41:17.176                     continue
2025-07-02 06:41:17.176                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.176                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.176                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.176                 # compares by a factor of 3.
2025-07-02 06:41:17.176                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.176                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.176                 # of the computation is cached by cruncher
2025-07-02 06:41:17.176                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.176                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.176                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.176                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.177         if best_ratio < cutoff:
2025-07-02 06:41:17.177             # no non-identical "pretty close" pair
2025-07-02 06:41:17.177             if eqi is None:
2025-07-02 06:41:17.177                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.177                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.177                 return
2025-07-02 06:41:17.177             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.177             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.177         else:
2025-07-02 06:41:17.177             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.177             eqi = None
2025-07-02 06:41:17.177
2025-07-02 06:41:17.177         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.177         # identical
2025-07-02 06:41:17.177
2025-07-02 06:41:17.177         # pump out diffs from before the synch point
2025-07-02 06:41:17.177         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.177
2025-07-02 06:41:17.177         # do intraline marking on the synch pair
2025-07-02 06:41:17.177         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.178         if eqi is None:
2025-07-02 06:41:17.178             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.178             atags = btags = ""
2025-07-02 06:41:17.178             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.178             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.178                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.178                 if tag == 'replace':
2025-07-02 06:41:17.178                     atags += '^' * la
2025-07-02 06:41:17.178                     btags += '^' * lb
2025-07-02 06:41:17.178                 elif tag == 'delete':
2025-07-02 06:41:17.178                     atags += '-' * la
2025-07-02 06:41:17.178                 elif tag == 'insert':
2025-07-02 06:41:17.178                     btags += '+' * lb
2025-07-02 06:41:17.178                 elif tag == 'equal':
2025-07-02 06:41:17.178                     atags += ' ' * la
2025-07-02 06:41:17.178                     btags += ' ' * lb
2025-07-02 06:41:17.178                 else:
2025-07-02 06:41:17.178                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.179             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.179         else:
2025-07-02 06:41:17.179             # the synch pair is identical
2025-07-02 06:41:17.179             yield '  ' + aelt
2025-07-02 06:41:17.179
2025-07-02 06:41:17.179         # pump out diffs from after the synch point
2025-07-02 06:41:17.179 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.179
2025-07-02 06:41:17.179 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.179 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.179
2025-07-02 06:41:17.179 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.179 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.179 alo = 185, ahi = 1101
2025-07-02 06:41:17.179 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.179 blo = 185, bhi = 1101
2025-07-02 06:41:17.179
2025-07-02 06:41:17.179     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.179         g = []
2025-07-02 06:41:17.180         if alo < ahi:
2025-07-02 06:41:17.180             if blo < bhi:
2025-07-02 06:41:17.180                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.180             else:
2025-07-02 06:41:17.180                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.180         elif blo < bhi:
2025-07-02 06:41:17.180             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.180
2025-07-02 06:41:17.180 >       yield from g
2025-07-02 06:41:17.180
2025-07-02 06:41:17.180 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.180 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.180
2025-07-02 06:41:17.180 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.180 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.180 alo = 185, ahi = 1101
2025-07-02 06:41:17.180 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.180 blo = 185, bhi = 1101
2025-07-02 06:41:17.180
2025-07-02 06:41:17.180     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.181         r"""
2025-07-02 06:41:17.181         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.181         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.181         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.181         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.181
2025-07-02 06:41:17.181         Example:
2025-07-02 06:41:17.181
2025-07-02 06:41:17.181         >>> d = Differ()
2025-07-02 06:41:17.181         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.181         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.181         >>> print(''.join(results), end="")
2025-07-02 06:41:17.181         - abcDefghiJkl
2025-07-02 06:41:17.181         + abcdefGhijkl
2025-07-02 06:41:17.181         """
2025-07-02 06:41:17.181
2025-07-02 06:41:17.181         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.181         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.181         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.182         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.182         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.182
2025-07-02 06:41:17.182         # search for the pair that matches best without being identical
2025-07-02 06:41:17.182         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.182         # on junk -- unless we have to)
2025-07-02 06:41:17.182         for j in range(blo, bhi):
2025-07-02 06:41:17.182             bj = b[j]
2025-07-02 06:41:17.182             cruncher.set_seq2(bj)
2025-07-02 06:41:17.182             for i in range(alo, ahi):
2025-07-02 06:41:17.182                 ai = a[i]
2025-07-02 06:41:17.182                 if ai == bj:
2025-07-02 06:41:17.182                     if eqi is None:
2025-07-02 06:41:17.182                         eqi, eqj = i, j
2025-07-02 06:41:17.182                     continue
2025-07-02 06:41:17.182                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.182                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.182                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.182                 # compares by a factor of 3.
2025-07-02 06:41:17.182                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.183                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.183                 # of the computation is cached by cruncher
2025-07-02 06:41:17.183                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.183                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.183                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.183                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.183         if best_ratio < cutoff:
2025-07-02 06:41:17.183             # no non-identical "pretty close" pair
2025-07-02 06:41:17.183             if eqi is None:
2025-07-02 06:41:17.183                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.183                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.183                 return
2025-07-02 06:41:17.183             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.183             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.183         else:
2025-07-02 06:41:17.183             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.183             eqi = None
2025-07-02 06:41:17.183
2025-07-02 06:41:17.183         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.183         # identical
2025-07-02 06:41:17.184
2025-07-02 06:41:17.184         # pump out diffs from before the synch point
2025-07-02 06:41:17.184         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.184
2025-07-02 06:41:17.184         # do intraline marking on the synch pair
2025-07-02 06:41:17.184         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.184         if eqi is None:
2025-07-02 06:41:17.184             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.184             atags = btags = ""
2025-07-02 06:41:17.184             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.184             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.184                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.184                 if tag == 'replace':
2025-07-02 06:41:17.184                     atags += '^' * la
2025-07-02 06:41:17.184                     btags += '^' * lb
2025-07-02 06:41:17.184                 elif tag == 'delete':
2025-07-02 06:41:17.184                     atags += '-' * la
2025-07-02 06:41:17.184                 elif tag == 'insert':
2025-07-02 06:41:17.184                     btags += '+' * lb
2025-07-02 06:41:17.184                 elif tag == 'equal':
2025-07-02 06:41:17.184                     atags += ' ' * la
2025-07-02 06:41:17.185                     btags += ' ' * lb
2025-07-02 06:41:17.185                 else:
2025-07-02 06:41:17.185                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.185             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.185         else:
2025-07-02 06:41:17.185             # the synch pair is identical
2025-07-02 06:41:17.185             yield '  ' + aelt
2025-07-02 06:41:17.185
2025-07-02 06:41:17.185         # pump out diffs from after the synch point
2025-07-02 06:41:17.185 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.185
2025-07-02 06:41:17.185 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.185 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.185
2025-07-02 06:41:17.185 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.185 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.185 alo = 186, ahi = 1101
2025-07-02 06:41:17.185 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.185 blo = 186, bhi = 1101
2025-07-02 06:41:17.185
2025-07-02 06:41:17.186     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.186         g = []
2025-07-02 06:41:17.186         if alo < ahi:
2025-07-02 06:41:17.186             if blo < bhi:
2025-07-02 06:41:17.186                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.186             else:
2025-07-02 06:41:17.186                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.186         elif blo < bhi:
2025-07-02 06:41:17.186             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.186
2025-07-02 06:41:17.186 >       yield from g
2025-07-02 06:41:17.186
2025-07-02 06:41:17.186 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.186 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.186
2025-07-02 06:41:17.186 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.186 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.186 alo = 186, ahi = 1101
2025-07-02 06:41:17.186 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.187 blo = 186, bhi = 1101
2025-07-02 06:41:17.187
2025-07-02 06:41:17.187     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.187         r"""
2025-07-02 06:41:17.187         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.187         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.187         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.187         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.187
2025-07-02 06:41:17.187         Example:
2025-07-02 06:41:17.187
2025-07-02 06:41:17.187         >>> d = Differ()
2025-07-02 06:41:17.187         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.187         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.187         >>> print(''.join(results), end="")
2025-07-02 06:41:17.187         - abcDefghiJkl
2025-07-02 06:41:17.188         + abcdefGhijkl
2025-07-02 06:41:17.188         """
2025-07-02 06:41:17.188
2025-07-02 06:41:17.188         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.188         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.188         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.188         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.188         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.188
2025-07-02 06:41:17.188         # search for the pair that matches best without being identical
2025-07-02 06:41:17.188         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.188         # on junk -- unless we have to)
2025-07-02 06:41:17.188         for j in range(blo, bhi):
2025-07-02 06:41:17.188             bj = b[j]
2025-07-02 06:41:17.188             cruncher.set_seq2(bj)
2025-07-02 06:41:17.188             for i in range(alo, ahi):
2025-07-02 06:41:17.188                 ai = a[i]
2025-07-02 06:41:17.188                 if ai == bj:
2025-07-02 06:41:17.189                     if eqi is None:
2025-07-02 06:41:17.189                         eqi, eqj = i, j
2025-07-02 06:41:17.189                     continue
2025-07-02 06:41:17.189                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.189                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.189                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.189                 # compares by a factor of 3.
2025-07-02 06:41:17.189                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.189                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.189                 # of the computation is cached by cruncher
2025-07-02 06:41:17.189                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.189                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.189                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.189                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.189         if best_ratio < cutoff:
2025-07-02 06:41:17.189             # no non-identical "pretty close" pair
2025-07-02 06:41:17.189             if eqi is None:
2025-07-02 06:41:17.189                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.189                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.189                 return
2025-07-02 06:41:17.190             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.190             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.190         else:
2025-07-02 06:41:17.190             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.190             eqi = None
2025-07-02 06:41:17.190
2025-07-02 06:41:17.190         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.190         # identical
2025-07-02 06:41:17.190
2025-07-02 06:41:17.190         # pump out diffs from before the synch point
2025-07-02 06:41:17.190         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.190
2025-07-02 06:41:17.190         # do intraline marking on the synch pair
2025-07-02 06:41:17.190         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.190         if eqi is None:
2025-07-02 06:41:17.190             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.190             atags = btags = ""
2025-07-02 06:41:17.190             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.190             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.190                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.190                 if tag == 'replace':
2025-07-02 06:41:17.191                     atags += '^' * la
2025-07-02 06:41:17.191                     btags += '^' * lb
2025-07-02 06:41:17.191                 elif tag == 'delete':
2025-07-02 06:41:17.191                     atags += '-' * la
2025-07-02 06:41:17.191                 elif tag == 'insert':
2025-07-02 06:41:17.191                     btags += '+' * lb
2025-07-02 06:41:17.191                 elif tag == 'equal':
2025-07-02 06:41:17.191                     atags += ' ' * la
2025-07-02 06:41:17.191                     btags += ' ' * lb
2025-07-02 06:41:17.191                 else:
2025-07-02 06:41:17.191                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.191             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.191         else:
2025-07-02 06:41:17.191             # the synch pair is identical
2025-07-02 06:41:17.191             yield '  ' + aelt
2025-07-02 06:41:17.191
2025-07-02 06:41:17.191         # pump out diffs from after the synch point
2025-07-02 06:41:17.191 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.191
2025-07-02 06:41:17.191 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.192 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.192
2025-07-02 06:41:17.192 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.192 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.192 alo = 187, ahi = 1101
2025-07-02 06:41:17.192 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.192 blo = 187, bhi = 1101
2025-07-02 06:41:17.192
2025-07-02 06:41:17.192     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.192         g = []
2025-07-02 06:41:17.192         if alo < ahi:
2025-07-02 06:41:17.192             if blo < bhi:
2025-07-02 06:41:17.192                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.192             else:
2025-07-02 06:41:17.192                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.192         elif blo < bhi:
2025-07-02 06:41:17.192             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.192
2025-07-02 06:41:17.192 >       yield from g
2025-07-02 06:41:17.192
2025-07-02 06:41:17.193 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.193 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.193
2025-07-02 06:41:17.193 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.193 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.193 alo = 187, ahi = 1101
2025-07-02 06:41:17.193 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.193 blo = 187, bhi = 1101
2025-07-02 06:41:17.193
2025-07-02 06:41:17.193     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.193         r"""
2025-07-02 06:41:17.193         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.193         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.193         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.193         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.193
2025-07-02 06:41:17.193         Example:
2025-07-02 06:41:17.193
2025-07-02 06:41:17.193         >>> d = Differ()
2025-07-02 06:41:17.193         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.193         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.194         >>> print(''.join(results), end="")
2025-07-02 06:41:17.194         - abcDefghiJkl
2025-07-02 06:41:17.194         + abcdefGhijkl
2025-07-02 06:41:17.194         """
2025-07-02 06:41:17.194
2025-07-02 06:41:17.194         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.194         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.194         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.194         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.194         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.194
2025-07-02 06:41:17.194         # search for the pair that matches best without being identical
2025-07-02 06:41:17.194         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.194         # on junk -- unless we have to)
2025-07-02 06:41:17.194         for j in range(blo, bhi):
2025-07-02 06:41:17.194             bj = b[j]
2025-07-02 06:41:17.194             cruncher.set_seq2(bj)
2025-07-02 06:41:17.194             for i in range(alo, ahi):
2025-07-02 06:41:17.195                 ai = a[i]
2025-07-02 06:41:17.195                 if ai == bj:
2025-07-02 06:41:17.195                     if eqi is None:
2025-07-02 06:41:17.195                         eqi, eqj = i, j
2025-07-02 06:41:17.195                     continue
2025-07-02 06:41:17.195                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.195                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.195                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.195                 # compares by a factor of 3.
2025-07-02 06:41:17.195                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.195                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.195                 # of the computation is cached by cruncher
2025-07-02 06:41:17.195                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.195                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.195                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.195                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.195         if best_ratio < cutoff:
2025-07-02 06:41:17.195             # no non-identical "pretty close" pair
2025-07-02 06:41:17.195             if eqi is None:
2025-07-02 06:41:17.196                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.196                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.196                 return
2025-07-02 06:41:17.196             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.196             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.196         else:
2025-07-02 06:41:17.196             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.196             eqi = None
2025-07-02 06:41:17.196
2025-07-02 06:41:17.196         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.196         # identical
2025-07-02 06:41:17.196
2025-07-02 06:41:17.196         # pump out diffs from before the synch point
2025-07-02 06:41:17.196         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.196
2025-07-02 06:41:17.196         # do intraline marking on the synch pair
2025-07-02 06:41:17.196         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.196         if eqi is None:
2025-07-02 06:41:17.196             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.196             atags = btags = ""
2025-07-02 06:41:17.197             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.197             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.197                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.197                 if tag == 'replace':
2025-07-02 06:41:17.197                     atags += '^' * la
2025-07-02 06:41:17.197                     btags += '^' * lb
2025-07-02 06:41:17.197                 elif tag == 'delete':
2025-07-02 06:41:17.197                     atags += '-' * la
2025-07-02 06:41:17.197                 elif tag == 'insert':
2025-07-02 06:41:17.197                     btags += '+' * lb
2025-07-02 06:41:17.197                 elif tag == 'equal':
2025-07-02 06:41:17.197                     atags += ' ' * la
2025-07-02 06:41:17.197                     btags += ' ' * lb
2025-07-02 06:41:17.197                 else:
2025-07-02 06:41:17.197                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.197             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.197         else:
2025-07-02 06:41:17.197             # the synch pair is identical
2025-07-02 06:41:17.197             yield '  ' + aelt
2025-07-02 06:41:17.197
2025-07-02 06:41:17.198         # pump out diffs from after the synch point
2025-07-02 06:41:17.198 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.198
2025-07-02 06:41:17.198 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.198 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.198
2025-07-02 06:41:17.198 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.198 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.198 alo = 188, ahi = 1101
2025-07-02 06:41:17.198 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.198 blo = 188, bhi = 1101
2025-07-02 06:41:17.198
2025-07-02 06:41:17.198     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.198         g = []
2025-07-02 06:41:17.198         if alo < ahi:
2025-07-02 06:41:17.198             if blo < bhi:
2025-07-02 06:41:17.198                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.198             else:
2025-07-02 06:41:17.198                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.198         elif blo < bhi:
2025-07-02 06:41:17.199             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.199
2025-07-02 06:41:17.199 >       yield from g
2025-07-02 06:41:17.199
2025-07-02 06:41:17.199 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.199 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.199
2025-07-02 06:41:17.199 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.199 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.199 alo = 188, ahi = 1101
2025-07-02 06:41:17.199 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.199 blo = 188, bhi = 1101
2025-07-02 06:41:17.199
2025-07-02 06:41:17.199     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.199         r"""
2025-07-02 06:41:17.199         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.199         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.199         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.199         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.199
2025-07-02 06:41:17.200         Example:
2025-07-02 06:41:17.200
2025-07-02 06:41:17.200         >>> d = Differ()
2025-07-02 06:41:17.200         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.200         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.200         >>> print(''.join(results), end="")
2025-07-02 06:41:17.200         - abcDefghiJkl
2025-07-02 06:41:17.200         + abcdefGhijkl
2025-07-02 06:41:17.200         """
2025-07-02 06:41:17.200
2025-07-02 06:41:17.200         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.200         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.200         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.200         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.200         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.200
2025-07-02 06:41:17.200         # search for the pair that matches best without being identical
2025-07-02 06:41:17.200         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.200         # on junk -- unless we have to)
2025-07-02 06:41:17.201         for j in range(blo, bhi):
2025-07-02 06:41:17.201             bj = b[j]
2025-07-02 06:41:17.201             cruncher.set_seq2(bj)
2025-07-02 06:41:17.201             for i in range(alo, ahi):
2025-07-02 06:41:17.201                 ai = a[i]
2025-07-02 06:41:17.201                 if ai == bj:
2025-07-02 06:41:17.201                     if eqi is None:
2025-07-02 06:41:17.201                         eqi, eqj = i, j
2025-07-02 06:41:17.201                     continue
2025-07-02 06:41:17.201                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.201                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.201                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.201                 # compares by a factor of 3.
2025-07-02 06:41:17.201                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.201                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.201                 # of the computation is cached by cruncher
2025-07-02 06:41:17.201                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.201                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.201                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.201                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.202         if best_ratio < cutoff:
2025-07-02 06:41:17.202             # no non-identical "pretty close" pair
2025-07-02 06:41:17.202             if eqi is None:
2025-07-02 06:41:17.202                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.202                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.202                 return
2025-07-02 06:41:17.202             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.202             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.202         else:
2025-07-02 06:41:17.202             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.202             eqi = None
2025-07-02 06:41:17.202
2025-07-02 06:41:17.202         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.202         # identical
2025-07-02 06:41:17.202
2025-07-02 06:41:17.202         # pump out diffs from before the synch point
2025-07-02 06:41:17.202         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.202
2025-07-02 06:41:17.202         # do intraline marking on the synch pair
2025-07-02 06:41:17.202         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.203         if eqi is None:
2025-07-02 06:41:17.203             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.203             atags = btags = ""
2025-07-02 06:41:17.203             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.203             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.203                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.203                 if tag == 'replace':
2025-07-02 06:41:17.203                     atags += '^' * la
2025-07-02 06:41:17.203                     btags += '^' * lb
2025-07-02 06:41:17.203                 elif tag == 'delete':
2025-07-02 06:41:17.203                     atags += '-' * la
2025-07-02 06:41:17.203                 elif tag == 'insert':
2025-07-02 06:41:17.203                     btags += '+' * lb
2025-07-02 06:41:17.203                 elif tag == 'equal':
2025-07-02 06:41:17.203                     atags += ' ' * la
2025-07-02 06:41:17.203                     btags += ' ' * lb
2025-07-02 06:41:17.203                 else:
2025-07-02 06:41:17.203                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.204             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.204         else:
2025-07-02 06:41:17.204             # the synch pair is identical
2025-07-02 06:41:17.204             yield '  ' + aelt
2025-07-02 06:41:17.204
2025-07-02 06:41:17.204         # pump out diffs from after the synch point
2025-07-02 06:41:17.204 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.204
2025-07-02 06:41:17.204 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.204 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.204
2025-07-02 06:41:17.204 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.204 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.204 alo = 189, ahi = 1101
2025-07-02 06:41:17.204 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.204 blo = 189, bhi = 1101
2025-07-02 06:41:17.204
2025-07-02 06:41:17.204     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.205         g = []
2025-07-02 06:41:17.205         if alo < ahi:
2025-07-02 06:41:17.205             if blo < bhi:
2025-07-02 06:41:17.205                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.205             else:
2025-07-02 06:41:17.205                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.205         elif blo < bhi:
2025-07-02 06:41:17.205             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.205
2025-07-02 06:41:17.205 >       yield from g
2025-07-02 06:41:17.205
2025-07-02 06:41:17.205 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.205 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.205
2025-07-02 06:41:17.205 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.205 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.205 alo = 189, ahi = 1101
2025-07-02 06:41:17.205 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.205 blo = 189, bhi = 1101
2025-07-02 06:41:17.206
2025-07-02 06:41:17.206     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.206         r"""
2025-07-02 06:41:17.206         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.206         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.206         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.206         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.206
2025-07-02 06:41:17.206         Example:
2025-07-02 06:41:17.206
2025-07-02 06:41:17.206         >>> d = Differ()
2025-07-02 06:41:17.206         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.206         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.206         >>> print(''.join(results), end="")
2025-07-02 06:41:17.206         - abcDefghiJkl
2025-07-02 06:41:17.206         + abcdefGhijkl
2025-07-02 06:41:17.206         """
2025-07-02 06:41:17.206
2025-07-02 06:41:17.206         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.207         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.207         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.207         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.207         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.207
2025-07-02 06:41:17.207         # search for the pair that matches best without being identical
2025-07-02 06:41:17.207         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.207         # on junk -- unless we have to)
2025-07-02 06:41:17.207         for j in range(blo, bhi):
2025-07-02 06:41:17.207             bj = b[j]
2025-07-02 06:41:17.207             cruncher.set_seq2(bj)
2025-07-02 06:41:17.207             for i in range(alo, ahi):
2025-07-02 06:41:17.207                 ai = a[i]
2025-07-02 06:41:17.207                 if ai == bj:
2025-07-02 06:41:17.207                     if eqi is None:
2025-07-02 06:41:17.207                         eqi, eqj = i, j
2025-07-02 06:41:17.207                     continue
2025-07-02 06:41:17.207                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.207                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.207                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.208                 # compares by a factor of 3.
2025-07-02 06:41:17.208                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.208                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.208                 # of the computation is cached by cruncher
2025-07-02 06:41:17.208                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.208                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.208                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.208                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.208         if best_ratio < cutoff:
2025-07-02 06:41:17.208             # no non-identical "pretty close" pair
2025-07-02 06:41:17.208             if eqi is None:
2025-07-02 06:41:17.208                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.208                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.208                 return
2025-07-02 06:41:17.208             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.208             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.208         else:
2025-07-02 06:41:17.208             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.208             eqi = None
2025-07-02 06:41:17.208
2025-07-02 06:41:17.209         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.209         # identical
2025-07-02 06:41:17.209
2025-07-02 06:41:17.209         # pump out diffs from before the synch point
2025-07-02 06:41:17.209         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.209
2025-07-02 06:41:17.209         # do intraline marking on the synch pair
2025-07-02 06:41:17.209         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.209         if eqi is None:
2025-07-02 06:41:17.209             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.209             atags = btags = ""
2025-07-02 06:41:17.209             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.209             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.209                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.209                 if tag == 'replace':
2025-07-02 06:41:17.209                     atags += '^' * la
2025-07-02 06:41:17.209                     btags += '^' * lb
2025-07-02 06:41:17.209                 elif tag == 'delete':
2025-07-02 06:41:17.209                     atags += '-' * la
2025-07-02 06:41:17.209                 elif tag == 'insert':
2025-07-02 06:41:17.209                     btags += '+' * lb
2025-07-02 06:41:17.210                 elif tag == 'equal':
2025-07-02 06:41:17.210                     atags += ' ' * la
2025-07-02 06:41:17.210                     btags += ' ' * lb
2025-07-02 06:41:17.210                 else:
2025-07-02 06:41:17.210                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.210             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.210         else:
2025-07-02 06:41:17.210             # the synch pair is identical
2025-07-02 06:41:17.210             yield '  ' + aelt
2025-07-02 06:41:17.210
2025-07-02 06:41:17.210         # pump out diffs from after the synch point
2025-07-02 06:41:17.210 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.210
2025-07-02 06:41:17.210 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.210 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.210
2025-07-02 06:41:17.210 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.210 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.210 alo = 190, ahi = 1101
2025-07-02 06:41:17.210 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.211 blo = 190, bhi = 1101
2025-07-02 06:41:17.211
2025-07-02 06:41:17.211     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.211         g = []
2025-07-02 06:41:17.211         if alo < ahi:
2025-07-02 06:41:17.211             if blo < bhi:
2025-07-02 06:41:17.211                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.211             else:
2025-07-02 06:41:17.211                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.211         elif blo < bhi:
2025-07-02 06:41:17.211             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.211
2025-07-02 06:41:17.211 >       yield from g
2025-07-02 06:41:17.211
2025-07-02 06:41:17.211 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.211 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.211
2025-07-02 06:41:17.211 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.211 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.211 alo = 190, ahi = 1101
2025-07-02 06:41:17.211 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.212 blo = 190, bhi = 1101
2025-07-02 06:41:17.212
2025-07-02 06:41:17.212     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.212         r"""
2025-07-02 06:41:17.212         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.212         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.212         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.212         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.212
2025-07-02 06:41:17.212         Example:
2025-07-02 06:41:17.212
2025-07-02 06:41:17.212         >>> d = Differ()
2025-07-02 06:41:17.212         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.212         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.212         >>> print(''.join(results), end="")
2025-07-02 06:41:17.212         - abcDefghiJkl
2025-07-02 06:41:17.212         + abcdefGhijkl
2025-07-02 06:41:17.213         """
2025-07-02 06:41:17.213
2025-07-02 06:41:17.213         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.213         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.213         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.213         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.213         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.213
2025-07-02 06:41:17.213         # search for the pair that matches best without being identical
2025-07-02 06:41:17.213         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.213         # on junk -- unless we have to)
2025-07-02 06:41:17.213         for j in range(blo, bhi):
2025-07-02 06:41:17.213             bj = b[j]
2025-07-02 06:41:17.213             cruncher.set_seq2(bj)
2025-07-02 06:41:17.213             for i in range(alo, ahi):
2025-07-02 06:41:17.213                 ai = a[i]
2025-07-02 06:41:17.213                 if ai == bj:
2025-07-02 06:41:17.213                     if eqi is None:
2025-07-02 06:41:17.213                         eqi, eqj = i, j
2025-07-02 06:41:17.213                     continue
2025-07-02 06:41:17.214                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.214                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.214                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.214                 # compares by a factor of 3.
2025-07-02 06:41:17.214                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.214                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.214                 # of the computation is cached by cruncher
2025-07-02 06:41:17.214                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.214                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.214                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.214                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.214         if best_ratio < cutoff:
2025-07-02 06:41:17.214             # no non-identical "pretty close" pair
2025-07-02 06:41:17.214             if eqi is None:
2025-07-02 06:41:17.214                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.214                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.214                 return
2025-07-02 06:41:17.214             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.214             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.215         else:
2025-07-02 06:41:17.215             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.215             eqi = None
2025-07-02 06:41:17.215
2025-07-02 06:41:17.215         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.215         # identical
2025-07-02 06:41:17.215
2025-07-02 06:41:17.215         # pump out diffs from before the synch point
2025-07-02 06:41:17.215         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.215
2025-07-02 06:41:17.215         # do intraline marking on the synch pair
2025-07-02 06:41:17.215         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.215         if eqi is None:
2025-07-02 06:41:17.215             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.215             atags = btags = ""
2025-07-02 06:41:17.215             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.215             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.215                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.215                 if tag == 'replace':
2025-07-02 06:41:17.215                     atags += '^' * la
2025-07-02 06:41:17.215                     btags += '^' * lb
2025-07-02 06:41:17.216                 elif tag == 'delete':
2025-07-02 06:41:17.216                     atags += '-' * la
2025-07-02 06:41:17.216                 elif tag == 'insert':
2025-07-02 06:41:17.216                     btags += '+' * lb
2025-07-02 06:41:17.216                 elif tag == 'equal':
2025-07-02 06:41:17.216                     atags += ' ' * la
2025-07-02 06:41:17.216                     btags += ' ' * lb
2025-07-02 06:41:17.216                 else:
2025-07-02 06:41:17.216                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.216             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.216         else:
2025-07-02 06:41:17.216             # the synch pair is identical
2025-07-02 06:41:17.216             yield '  ' + aelt
2025-07-02 06:41:17.216
2025-07-02 06:41:17.216         # pump out diffs from after the synch point
2025-07-02 06:41:17.216 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.216
2025-07-02 06:41:17.216 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.216 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.216
2025-07-02 06:41:17.216 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.217 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.217 alo = 191, ahi = 1101
2025-07-02 06:41:17.217 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.217 blo = 191, bhi = 1101
2025-07-02 06:41:17.217
2025-07-02 06:41:17.217     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.217         g = []
2025-07-02 06:41:17.217         if alo < ahi:
2025-07-02 06:41:17.217             if blo < bhi:
2025-07-02 06:41:17.217                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.217             else:
2025-07-02 06:41:17.217                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.217         elif blo < bhi:
2025-07-02 06:41:17.217             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.217
2025-07-02 06:41:17.217 >       yield from g
2025-07-02 06:41:17.217
2025-07-02 06:41:17.217 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.217 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.217
2025-07-02 06:41:17.218 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.218 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.218 alo = 191, ahi = 1101
2025-07-02 06:41:17.218 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.218 blo = 191, bhi = 1101
2025-07-02 06:41:17.218
2025-07-02 06:41:17.218     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.218         r"""
2025-07-02 06:41:17.218         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.218         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.218         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.218         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.218
2025-07-02 06:41:17.218         Example:
2025-07-02 06:41:17.218
2025-07-02 06:41:17.218         >>> d = Differ()
2025-07-02 06:41:17.218         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.218         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.218         >>> print(''.join(results), end="")
2025-07-02 06:41:17.218         - abcDefghiJkl
2025-07-02 06:41:17.219         + abcdefGhijkl
2025-07-02 06:41:17.219         """
2025-07-02 06:41:17.219
2025-07-02 06:41:17.219         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.219         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.219         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.219         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.219         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.219
2025-07-02 06:41:17.219         # search for the pair that matches best without being identical
2025-07-02 06:41:17.219         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.219         # on junk -- unless we have to)
2025-07-02 06:41:17.219         for j in range(blo, bhi):
2025-07-02 06:41:17.219             bj = b[j]
2025-07-02 06:41:17.219             cruncher.set_seq2(bj)
2025-07-02 06:41:17.219             for i in range(alo, ahi):
2025-07-02 06:41:17.220                 ai = a[i]
2025-07-02 06:41:17.220                 if ai == bj:
2025-07-02 06:41:17.220                     if eqi is None:
2025-07-02 06:41:17.220                         eqi, eqj = i, j
2025-07-02 06:41:17.220                     continue
2025-07-02 06:41:17.220                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.220                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.220                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.220                 # compares by a factor of 3.
2025-07-02 06:41:17.220                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.220                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.220                 # of the computation is cached by cruncher
2025-07-02 06:41:17.220                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.220                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.220                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.220                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.220         if best_ratio < cutoff:
2025-07-02 06:41:17.220             # no non-identical "pretty close" pair
2025-07-02 06:41:17.220             if eqi is None:
2025-07-02 06:41:17.220                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.221                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.221                 return
2025-07-02 06:41:17.221             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.221             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.221         else:
2025-07-02 06:41:17.221             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.221             eqi = None
2025-07-02 06:41:17.221
2025-07-02 06:41:17.221         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.221         # identical
2025-07-02 06:41:17.221
2025-07-02 06:41:17.221         # pump out diffs from before the synch point
2025-07-02 06:41:17.221         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.221
2025-07-02 06:41:17.221         # do intraline marking on the synch pair
2025-07-02 06:41:17.221         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.221         if eqi is None:
2025-07-02 06:41:17.221             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.222             atags = btags = ""
2025-07-02 06:41:17.222             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.222             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.222                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.222                 if tag == 'replace':
2025-07-02 06:41:17.222                     atags += '^' * la
2025-07-02 06:41:17.222                     btags += '^' * lb
2025-07-02 06:41:17.222                 elif tag == 'delete':
2025-07-02 06:41:17.222                     atags += '-' * la
2025-07-02 06:41:17.222                 elif tag == 'insert':
2025-07-02 06:41:17.222                     btags += '+' * lb
2025-07-02 06:41:17.222                 elif tag == 'equal':
2025-07-02 06:41:17.222                     atags += ' ' * la
2025-07-02 06:41:17.222                     btags += ' ' * lb
2025-07-02 06:41:17.222                 else:
2025-07-02 06:41:17.222                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.222             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.222         else:
2025-07-02 06:41:17.222             # the synch pair is identical
2025-07-02 06:41:17.222             yield '  ' + aelt
2025-07-02 06:41:17.223
2025-07-02 06:41:17.223         # pump out diffs from after the synch point
2025-07-02 06:41:17.223 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.223
2025-07-02 06:41:17.223 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.223 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.223
2025-07-02 06:41:17.223 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.223 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.223 alo = 192, ahi = 1101
2025-07-02 06:41:17.223 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.223 blo = 192, bhi = 1101
2025-07-02 06:41:17.223
2025-07-02 06:41:17.223     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.223         g = []
2025-07-02 06:41:17.223         if alo < ahi:
2025-07-02 06:41:17.223             if blo < bhi:
2025-07-02 06:41:17.223                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.223             else:
2025-07-02 06:41:17.223                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.224         elif blo < bhi:
2025-07-02 06:41:17.224             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.224
2025-07-02 06:41:17.224 >       yield from g
2025-07-02 06:41:17.224
2025-07-02 06:41:17.224 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.224 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.224
2025-07-02 06:41:17.224 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.224 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.224 alo = 192, ahi = 1101
2025-07-02 06:41:17.224 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.224 blo = 192, bhi = 1101
2025-07-02 06:41:17.224
2025-07-02 06:41:17.224     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.224         r"""
2025-07-02 06:41:17.224         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.224         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.224         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.224         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.225
2025-07-02 06:41:17.225         Example:
2025-07-02 06:41:17.225
2025-07-02 06:41:17.225         >>> d = Differ()
2025-07-02 06:41:17.225         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.225         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.225         >>> print(''.join(results), end="")
2025-07-02 06:41:17.225         - abcDefghiJkl
2025-07-02 06:41:17.225         + abcdefGhijkl
2025-07-02 06:41:17.225         """
2025-07-02 06:41:17.225
2025-07-02 06:41:17.225         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.225         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.225         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.225         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.225         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.225
2025-07-02 06:41:17.225         # search for the pair that matches best without being identical
2025-07-02 06:41:17.225         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.226         # on junk -- unless we have to)
2025-07-02 06:41:17.226         for j in range(blo, bhi):
2025-07-02 06:41:17.226             bj = b[j]
2025-07-02 06:41:17.226             cruncher.set_seq2(bj)
2025-07-02 06:41:17.226             for i in range(alo, ahi):
2025-07-02 06:41:17.226                 ai = a[i]
2025-07-02 06:41:17.226                 if ai == bj:
2025-07-02 06:41:17.226                     if eqi is None:
2025-07-02 06:41:17.226                         eqi, eqj = i, j
2025-07-02 06:41:17.226                     continue
2025-07-02 06:41:17.226                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.226                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.226                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.226                 # compares by a factor of 3.
2025-07-02 06:41:17.226                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.226                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.226                 # of the computation is cached by cruncher
2025-07-02 06:41:17.226                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.226                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.226                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.227                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.227         if best_ratio < cutoff:
2025-07-02 06:41:17.227             # no non-identical "pretty close" pair
2025-07-02 06:41:17.227             if eqi is None:
2025-07-02 06:41:17.227                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.227                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.227                 return
2025-07-02 06:41:17.227             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.227             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.227         else:
2025-07-02 06:41:17.227             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.227             eqi = None
2025-07-02 06:41:17.227
2025-07-02 06:41:17.227         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.227         # identical
2025-07-02 06:41:17.227
2025-07-02 06:41:17.227         # pump out diffs from before the synch point
2025-07-02 06:41:17.227         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.227
2025-07-02 06:41:17.227         # do intraline marking on the synch pair
2025-07-02 06:41:17.227         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.228         if eqi is None:
2025-07-02 06:41:17.228             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.228             atags = btags = ""
2025-07-02 06:41:17.228             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.228             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.228                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.228                 if tag == 'replace':
2025-07-02 06:41:17.228                     atags += '^' * la
2025-07-02 06:41:17.228                     btags += '^' * lb
2025-07-02 06:41:17.228                 elif tag == 'delete':
2025-07-02 06:41:17.228                     atags += '-' * la
2025-07-02 06:41:17.228                 elif tag == 'insert':
2025-07-02 06:41:17.228                     btags += '+' * lb
2025-07-02 06:41:17.228                 elif tag == 'equal':
2025-07-02 06:41:17.228                     atags += ' ' * la
2025-07-02 06:41:17.228                     btags += ' ' * lb
2025-07-02 06:41:17.228                 else:
2025-07-02 06:41:17.228                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.228             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.228         else:
2025-07-02 06:41:17.229             # the synch pair is identical
2025-07-02 06:41:17.229             yield '  ' + aelt
2025-07-02 06:41:17.229
2025-07-02 06:41:17.229         # pump out diffs from after the synch point
2025-07-02 06:41:17.229 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.229
2025-07-02 06:41:17.229 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.229 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.229
2025-07-02 06:41:17.229 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.229 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.229 alo = 193, ahi = 1101
2025-07-02 06:41:17.229 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.229 blo = 193, bhi = 1101
2025-07-02 06:41:17.229
2025-07-02 06:41:17.229     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.229         g = []
2025-07-02 06:41:17.229         if alo < ahi:
2025-07-02 06:41:17.229             if blo < bhi:
2025-07-02 06:41:17.230                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.230             else:
2025-07-02 06:41:17.230                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.230         elif blo < bhi:
2025-07-02 06:41:17.230             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.230
2025-07-02 06:41:17.230 >       yield from g
2025-07-02 06:41:17.230
2025-07-02 06:41:17.230 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.230 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.230
2025-07-02 06:41:17.230 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.230 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.230 alo = 193, ahi = 1101
2025-07-02 06:41:17.230 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.230 blo = 193, bhi = 1101
2025-07-02 06:41:17.230
2025-07-02 06:41:17.230     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.230         r"""
2025-07-02 06:41:17.230         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.231         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.231         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.231         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.231
2025-07-02 06:41:17.231         Example:
2025-07-02 06:41:17.231
2025-07-02 06:41:17.231         >>> d = Differ()
2025-07-02 06:41:17.231         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.231         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.231         >>> print(''.join(results), end="")
2025-07-02 06:41:17.231         - abcDefghiJkl
2025-07-02 06:41:17.231         + abcdefGhijkl
2025-07-02 06:41:17.231         """
2025-07-02 06:41:17.231
2025-07-02 06:41:17.231         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.231         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.231         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.232         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.232         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.232
2025-07-02 06:41:17.232         # search for the pair that matches best without being identical
2025-07-02 06:41:17.232         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.232         # on junk -- unless we have to)
2025-07-02 06:41:17.232         for j in range(blo, bhi):
2025-07-02 06:41:17.232             bj = b[j]
2025-07-02 06:41:17.232             cruncher.set_seq2(bj)
2025-07-02 06:41:17.232             for i in range(alo, ahi):
2025-07-02 06:41:17.232                 ai = a[i]
2025-07-02 06:41:17.232                 if ai == bj:
2025-07-02 06:41:17.232                     if eqi is None:
2025-07-02 06:41:17.232                         eqi, eqj = i, j
2025-07-02 06:41:17.232                     continue
2025-07-02 06:41:17.232                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.232                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.232                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.232                 # compares by a factor of 3.
2025-07-02 06:41:17.232                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.232                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.233                 # of the computation is cached by cruncher
2025-07-02 06:41:17.233                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.233                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.233                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.233                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.233         if best_ratio < cutoff:
2025-07-02 06:41:17.233             # no non-identical "pretty close" pair
2025-07-02 06:41:17.233             if eqi is None:
2025-07-02 06:41:17.233                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.233                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.233                 return
2025-07-02 06:41:17.233             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.233             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.233         else:
2025-07-02 06:41:17.233             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.233             eqi = None
2025-07-02 06:41:17.233
2025-07-02 06:41:17.233         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.233         # identical
2025-07-02 06:41:17.233
2025-07-02 06:41:17.234         # pump out diffs from before the synch point
2025-07-02 06:41:17.234         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.234
2025-07-02 06:41:17.234         # do intraline marking on the synch pair
2025-07-02 06:41:17.234         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.234         if eqi is None:
2025-07-02 06:41:17.234             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.234             atags = btags = ""
2025-07-02 06:41:17.234             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.234             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.234                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.234                 if tag == 'replace':
2025-07-02 06:41:17.234                     atags += '^' * la
2025-07-02 06:41:17.234                     btags += '^' * lb
2025-07-02 06:41:17.234                 elif tag == 'delete':
2025-07-02 06:41:17.234                     atags += '-' * la
2025-07-02 06:41:17.234                 elif tag == 'insert':
2025-07-02 06:41:17.234                     btags += '+' * lb
2025-07-02 06:41:17.234                 elif tag == 'equal':
2025-07-02 06:41:17.234                     atags += ' ' * la
2025-07-02 06:41:17.234                     btags += ' ' * lb
2025-07-02 06:41:17.235                 else:
2025-07-02 06:41:17.235                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.235             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.235         else:
2025-07-02 06:41:17.235             # the synch pair is identical
2025-07-02 06:41:17.235             yield '  ' + aelt
2025-07-02 06:41:17.235
2025-07-02 06:41:17.235         # pump out diffs from after the synch point
2025-07-02 06:41:17.235 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.235
2025-07-02 06:41:17.235 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.235 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.235
2025-07-02 06:41:17.235 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.235 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.235 alo = 194, ahi = 1101
2025-07-02 06:41:17.235 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.236 blo = 194, bhi = 1101
2025-07-02 06:41:17.236
2025-07-02 06:41:17.236     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.236         g = []
2025-07-02 06:41:17.236         if alo < ahi:
2025-07-02 06:41:17.236             if blo < bhi:
2025-07-02 06:41:17.236                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.236             else:
2025-07-02 06:41:17.236                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.236         elif blo < bhi:
2025-07-02 06:41:17.236             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.236
2025-07-02 06:41:17.236 >       yield from g
2025-07-02 06:41:17.236
2025-07-02 06:41:17.236 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.236 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.236
2025-07-02 06:41:17.236 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.236 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.236 alo = 194, ahi = 1101
2025-07-02 06:41:17.237 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.237 blo = 194, bhi = 1101
2025-07-02 06:41:17.237
2025-07-02 06:41:17.237     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.237         r"""
2025-07-02 06:41:17.237         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.237         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.237         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.237         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.237
2025-07-02 06:41:17.237         Example:
2025-07-02 06:41:17.237
2025-07-02 06:41:17.237         >>> d = Differ()
2025-07-02 06:41:17.237         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.237         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.237         >>> print(''.join(results), end="")
2025-07-02 06:41:17.237         - abcDefghiJkl
2025-07-02 06:41:17.237         + abcdefGhijkl
2025-07-02 06:41:17.238         """
2025-07-02 06:41:17.238
2025-07-02 06:41:17.238         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.238         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.238         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.238         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.238         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.238
2025-07-02 06:41:17.238         # search for the pair that matches best without being identical
2025-07-02 06:41:17.238         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.238         # on junk -- unless we have to)
2025-07-02 06:41:17.238         for j in range(blo, bhi):
2025-07-02 06:41:17.238             bj = b[j]
2025-07-02 06:41:17.238             cruncher.set_seq2(bj)
2025-07-02 06:41:17.238             for i in range(alo, ahi):
2025-07-02 06:41:17.238                 ai = a[i]
2025-07-02 06:41:17.238                 if ai == bj:
2025-07-02 06:41:17.238                     if eqi is None:
2025-07-02 06:41:17.239                         eqi, eqj = i, j
2025-07-02 06:41:17.239                     continue
2025-07-02 06:41:17.239                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.239                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.239                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.239                 # compares by a factor of 3.
2025-07-02 06:41:17.239                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.239                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.239                 # of the computation is cached by cruncher
2025-07-02 06:41:17.239                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.239                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.239                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.239                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.239         if best_ratio < cutoff:
2025-07-02 06:41:17.239             # no non-identical "pretty close" pair
2025-07-02 06:41:17.239             if eqi is None:
2025-07-02 06:41:17.239                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.239                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.239                 return
2025-07-02 06:41:17.240             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.240             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.240         else:
2025-07-02 06:41:17.240             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.240             eqi = None
2025-07-02 06:41:17.240
2025-07-02 06:41:17.240         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.240         # identical
2025-07-02 06:41:17.240
2025-07-02 06:41:17.240         # pump out diffs from before the synch point
2025-07-02 06:41:17.240         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.240
2025-07-02 06:41:17.240         # do intraline marking on the synch pair
2025-07-02 06:41:17.240         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.240         if eqi is None:
2025-07-02 06:41:17.240             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.240             atags = btags = ""
2025-07-02 06:41:17.240             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.240             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.240                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.241                 if tag == 'replace':
2025-07-02 06:41:17.241                     atags += '^' * la
2025-07-02 06:41:17.241                     btags += '^' * lb
2025-07-02 06:41:17.241                 elif tag == 'delete':
2025-07-02 06:41:17.241                     atags += '-' * la
2025-07-02 06:41:17.241                 elif tag == 'insert':
2025-07-02 06:41:17.241                     btags += '+' * lb
2025-07-02 06:41:17.241                 elif tag == 'equal':
2025-07-02 06:41:17.241                     atags += ' ' * la
2025-07-02 06:41:17.241                     btags += ' ' * lb
2025-07-02 06:41:17.241                 else:
2025-07-02 06:41:17.241                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.241             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.241         else:
2025-07-02 06:41:17.241             # the synch pair is identical
2025-07-02 06:41:17.241             yield '  ' + aelt
2025-07-02 06:41:17.241
2025-07-02 06:41:17.241         # pump out diffs from after the synch point
2025-07-02 06:41:17.241 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.241
2025-07-02 06:41:17.241 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.242 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.242
2025-07-02 06:41:17.242 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.242 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.242 alo = 195, ahi = 1101
2025-07-02 06:41:17.242 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.242 blo = 195, bhi = 1101
2025-07-02 06:41:17.242
2025-07-02 06:41:17.242     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.242         g = []
2025-07-02 06:41:17.242         if alo < ahi:
2025-07-02 06:41:17.242             if blo < bhi:
2025-07-02 06:41:17.242                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.242             else:
2025-07-02 06:41:17.242                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.242         elif blo < bhi:
2025-07-02 06:41:17.242             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.242
2025-07-02 06:41:17.242 >       yield from g
2025-07-02 06:41:17.242
2025-07-02 06:41:17.243 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.243 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.243
2025-07-02 06:41:17.243 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.243 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.243 alo = 195, ahi = 1101
2025-07-02 06:41:17.243 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.243 blo = 195, bhi = 1101
2025-07-02 06:41:17.243
2025-07-02 06:41:17.243     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.243         r"""
2025-07-02 06:41:17.243         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.243         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.243         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.243         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.243
2025-07-02 06:41:17.243         Example:
2025-07-02 06:41:17.243
2025-07-02 06:41:17.243         >>> d = Differ()
2025-07-02 06:41:17.244         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.244         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.244         >>> print(''.join(results), end="")
2025-07-02 06:41:17.244         - abcDefghiJkl
2025-07-02 06:41:17.244         + abcdefGhijkl
2025-07-02 06:41:17.244         """
2025-07-02 06:41:17.244
2025-07-02 06:41:17.244         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.244         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.244         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.244         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.244         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.244
2025-07-02 06:41:17.244         # search for the pair that matches best without being identical
2025-07-02 06:41:17.244         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.244         # on junk -- unless we have to)
2025-07-02 06:41:17.244         for j in range(blo, bhi):
2025-07-02 06:41:17.244             bj = b[j]
2025-07-02 06:41:17.245             cruncher.set_seq2(bj)
2025-07-02 06:41:17.245             for i in range(alo, ahi):
2025-07-02 06:41:17.245                 ai = a[i]
2025-07-02 06:41:17.245                 if ai == bj:
2025-07-02 06:41:17.245                     if eqi is None:
2025-07-02 06:41:17.245                         eqi, eqj = i, j
2025-07-02 06:41:17.245                     continue
2025-07-02 06:41:17.245                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.245                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.245                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.245                 # compares by a factor of 3.
2025-07-02 06:41:17.245                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.245                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.245                 # of the computation is cached by cruncher
2025-07-02 06:41:17.245                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.245                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.245                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.245                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.245         if best_ratio < cutoff:
2025-07-02 06:41:17.245             # no non-identical "pretty close" pair
2025-07-02 06:41:17.246             if eqi is None:
2025-07-02 06:41:17.246                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.246                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.246                 return
2025-07-02 06:41:17.246             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.246             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.246         else:
2025-07-02 06:41:17.246             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.246             eqi = None
2025-07-02 06:41:17.246
2025-07-02 06:41:17.246         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.246         # identical
2025-07-02 06:41:17.246
2025-07-02 06:41:17.246         # pump out diffs from before the synch point
2025-07-02 06:41:17.246         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.246
2025-07-02 06:41:17.246         # do intraline marking on the synch pair
2025-07-02 06:41:17.246         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.246         if eqi is None:
2025-07-02 06:41:17.246             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.247             atags = btags = ""
2025-07-02 06:41:17.247             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.247             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.247                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.247                 if tag == 'replace':
2025-07-02 06:41:17.247                     atags += '^' * la
2025-07-02 06:41:17.247                     btags += '^' * lb
2025-07-02 06:41:17.247                 elif tag == 'delete':
2025-07-02 06:41:17.247                     atags += '-' * la
2025-07-02 06:41:17.247                 elif tag == 'insert':
2025-07-02 06:41:17.247                     btags += '+' * lb
2025-07-02 06:41:17.247                 elif tag == 'equal':
2025-07-02 06:41:17.247                     atags += ' ' * la
2025-07-02 06:41:17.247                     btags += ' ' * lb
2025-07-02 06:41:17.247                 else:
2025-07-02 06:41:17.247                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.247             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.247         else:
2025-07-02 06:41:17.247             # the synch pair is identical
2025-07-02 06:41:17.248             yield '  ' + aelt
2025-07-02 06:41:17.248
2025-07-02 06:41:17.248         # pump out diffs from after the synch point
2025-07-02 06:41:17.248 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.248
2025-07-02 06:41:17.248 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.248 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.248
2025-07-02 06:41:17.248 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.248 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.248 alo = 196, ahi = 1101
2025-07-02 06:41:17.248 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.248 blo = 196, bhi = 1101
2025-07-02 06:41:17.248
2025-07-02 06:41:17.248     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.248         g = []
2025-07-02 06:41:17.248         if alo < ahi:
2025-07-02 06:41:17.248             if blo < bhi:
2025-07-02 06:41:17.248                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.249             else:
2025-07-02 06:41:17.249                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.249         elif blo < bhi:
2025-07-02 06:41:17.249             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.249
2025-07-02 06:41:17.249 >       yield from g
2025-07-02 06:41:17.249
2025-07-02 06:41:17.249 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.249 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.249
2025-07-02 06:41:17.249 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.249 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.249 alo = 196, ahi = 1101
2025-07-02 06:41:17.249 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.249 blo = 196, bhi = 1101
2025-07-02 06:41:17.249
2025-07-02 06:41:17.249     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.249         r"""
2025-07-02 06:41:17.249         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.249         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.250         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.250         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.250
2025-07-02 06:41:17.250         Example:
2025-07-02 06:41:17.250
2025-07-02 06:41:17.250         >>> d = Differ()
2025-07-02 06:41:17.250         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.250         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.250         >>> print(''.join(results), end="")
2025-07-02 06:41:17.250         - abcDefghiJkl
2025-07-02 06:41:17.250         + abcdefGhijkl
2025-07-02 06:41:17.250         """
2025-07-02 06:41:17.250
2025-07-02 06:41:17.250         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.250         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.250         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.250         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.250         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.251
2025-07-02 06:41:17.251         # search for the pair that matches best without being identical
2025-07-02 06:41:17.251         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.251         # on junk -- unless we have to)
2025-07-02 06:41:17.251         for j in range(blo, bhi):
2025-07-02 06:41:17.251             bj = b[j]
2025-07-02 06:41:17.251             cruncher.set_seq2(bj)
2025-07-02 06:41:17.251             for i in range(alo, ahi):
2025-07-02 06:41:17.251                 ai = a[i]
2025-07-02 06:41:17.251                 if ai == bj:
2025-07-02 06:41:17.251                     if eqi is None:
2025-07-02 06:41:17.251                         eqi, eqj = i, j
2025-07-02 06:41:17.251                     continue
2025-07-02 06:41:17.251                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.251                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.251                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.251                 # compares by a factor of 3.
2025-07-02 06:41:17.251                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.252                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.252                 # of the computation is cached by cruncher
2025-07-02 06:41:17.252                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.252                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.252                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.252                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.252         if best_ratio < cutoff:
2025-07-02 06:41:17.252             # no non-identical "pretty close" pair
2025-07-02 06:41:17.252             if eqi is None:
2025-07-02 06:41:17.252                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.252                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.252                 return
2025-07-02 06:41:17.252             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.252             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.252         else:
2025-07-02 06:41:17.252             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.252             eqi = None
2025-07-02 06:41:17.252
2025-07-02 06:41:17.252         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.253         # identical
2025-07-02 06:41:17.253
2025-07-02 06:41:17.253         # pump out diffs from before the synch point
2025-07-02 06:41:17.253         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.253
2025-07-02 06:41:17.253         # do intraline marking on the synch pair
2025-07-02 06:41:17.253         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.253         if eqi is None:
2025-07-02 06:41:17.253             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.253             atags = btags = ""
2025-07-02 06:41:17.253             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.253             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.253                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.253                 if tag == 'replace':
2025-07-02 06:41:17.253                     atags += '^' * la
2025-07-02 06:41:17.253                     btags += '^' * lb
2025-07-02 06:41:17.253                 elif tag == 'delete':
2025-07-02 06:41:17.253                     atags += '-' * la
2025-07-02 06:41:17.253                 elif tag == 'insert':
2025-07-02 06:41:17.253                     btags += '+' * lb
2025-07-02 06:41:17.253                 elif tag == 'equal':
2025-07-02 06:41:17.254                     atags += ' ' * la
2025-07-02 06:41:17.254                     btags += ' ' * lb
2025-07-02 06:41:17.254                 else:
2025-07-02 06:41:17.254                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.254             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.254         else:
2025-07-02 06:41:17.254             # the synch pair is identical
2025-07-02 06:41:17.254             yield '  ' + aelt
2025-07-02 06:41:17.254
2025-07-02 06:41:17.254         # pump out diffs from after the synch point
2025-07-02 06:41:17.254 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.254
2025-07-02 06:41:17.254 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.254 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.254
2025-07-02 06:41:17.254 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.254 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.254 alo = 197, ahi = 1101
2025-07-02 06:41:17.254 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.254 blo = 197, bhi = 1101
2025-07-02 06:41:17.255
2025-07-02 06:41:17.255     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.255         g = []
2025-07-02 06:41:17.255         if alo < ahi:
2025-07-02 06:41:17.255             if blo < bhi:
2025-07-02 06:41:17.255                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.255             else:
2025-07-02 06:41:17.255                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.255         elif blo < bhi:
2025-07-02 06:41:17.255             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.255
2025-07-02 06:41:17.255 >       yield from g
2025-07-02 06:41:17.255
2025-07-02 06:41:17.255 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.255 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.255
2025-07-02 06:41:17.255 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.255 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.255 alo = 197, ahi = 1101
2025-07-02 06:41:17.255 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.256 blo = 197, bhi = 1101
2025-07-02 06:41:17.256
2025-07-02 06:41:17.256     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.256         r"""
2025-07-02 06:41:17.256         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.256         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.256         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.256         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.256
2025-07-02 06:41:17.256         Example:
2025-07-02 06:41:17.256
2025-07-02 06:41:17.256         >>> d = Differ()
2025-07-02 06:41:17.256         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.256         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.256         >>> print(''.join(results), end="")
2025-07-02 06:41:17.256         - abcDefghiJkl
2025-07-02 06:41:17.256         + abcdefGhijkl
2025-07-02 06:41:17.257         """
2025-07-02 06:41:17.257
2025-07-02 06:41:17.257         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.257         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.257         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.257         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.257         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.257
2025-07-02 06:41:17.257         # search for the pair that matches best without being identical
2025-07-02 06:41:17.257         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.257         # on junk -- unless we have to)
2025-07-02 06:41:17.257         for j in range(blo, bhi):
2025-07-02 06:41:17.257             bj = b[j]
2025-07-02 06:41:17.257             cruncher.set_seq2(bj)
2025-07-02 06:41:17.257             for i in range(alo, ahi):
2025-07-02 06:41:17.257                 ai = a[i]
2025-07-02 06:41:17.257                 if ai == bj:
2025-07-02 06:41:17.257                     if eqi is None:
2025-07-02 06:41:17.258                         eqi, eqj = i, j
2025-07-02 06:41:17.258                     continue
2025-07-02 06:41:17.258                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.258                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.258                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.258                 # compares by a factor of 3.
2025-07-02 06:41:17.258                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.258                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.258                 # of the computation is cached by cruncher
2025-07-02 06:41:17.258                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.258                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.258                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.258                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.258         if best_ratio < cutoff:
2025-07-02 06:41:17.258             # no non-identical "pretty close" pair
2025-07-02 06:41:17.258             if eqi is None:
2025-07-02 06:41:17.258                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.258                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.258                 return
2025-07-02 06:41:17.258             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.259             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.259         else:
2025-07-02 06:41:17.259             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.259             eqi = None
2025-07-02 06:41:17.259
2025-07-02 06:41:17.259         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.259         # identical
2025-07-02 06:41:17.259
2025-07-02 06:41:17.259         # pump out diffs from before the synch point
2025-07-02 06:41:17.259         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.259
2025-07-02 06:41:17.259         # do intraline marking on the synch pair
2025-07-02 06:41:17.259         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.259         if eqi is None:
2025-07-02 06:41:17.259             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.259             atags = btags = ""
2025-07-02 06:41:17.259             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.259             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.259                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.259                 if tag == 'replace':
2025-07-02 06:41:17.260                     atags += '^' * la
2025-07-02 06:41:17.260                     btags += '^' * lb
2025-07-02 06:41:17.260                 elif tag == 'delete':
2025-07-02 06:41:17.260                     atags += '-' * la
2025-07-02 06:41:17.260                 elif tag == 'insert':
2025-07-02 06:41:17.260                     btags += '+' * lb
2025-07-02 06:41:17.260                 elif tag == 'equal':
2025-07-02 06:41:17.260                     atags += ' ' * la
2025-07-02 06:41:17.260                     btags += ' ' * lb
2025-07-02 06:41:17.260                 else:
2025-07-02 06:41:17.260                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.260             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.260         else:
2025-07-02 06:41:17.260             # the synch pair is identical
2025-07-02 06:41:17.260             yield '  ' + aelt
2025-07-02 06:41:17.260
2025-07-02 06:41:17.260         # pump out diffs from after the synch point
2025-07-02 06:41:17.260 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.260
2025-07-02 06:41:17.260 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.260 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.261
2025-07-02 06:41:17.261 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.261 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.261 alo = 198, ahi = 1101
2025-07-02 06:41:17.261 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.261 blo = 198, bhi = 1101
2025-07-02 06:41:17.261
2025-07-02 06:41:17.261     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.261         g = []
2025-07-02 06:41:17.261         if alo < ahi:
2025-07-02 06:41:17.261             if blo < bhi:
2025-07-02 06:41:17.261                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.261             else:
2025-07-02 06:41:17.261                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.261         elif blo < bhi:
2025-07-02 06:41:17.261             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.261
2025-07-02 06:41:17.261 >       yield from g
2025-07-02 06:41:17.261
2025-07-02 06:41:17.261 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.262 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.262
2025-07-02 06:41:17.262 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.262 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.262 alo = 198, ahi = 1101
2025-07-02 06:41:17.262 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.262 blo = 198, bhi = 1101
2025-07-02 06:41:17.262
2025-07-02 06:41:17.262     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.262         r"""
2025-07-02 06:41:17.262         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.262         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.262         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.262         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.262
2025-07-02 06:41:17.262         Example:
2025-07-02 06:41:17.262
2025-07-02 06:41:17.262         >>> d = Differ()
2025-07-02 06:41:17.262         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.262         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.263         >>> print(''.join(results), end="")
2025-07-02 06:41:17.263         - abcDefghiJkl
2025-07-02 06:41:17.263         + abcdefGhijkl
2025-07-02 06:41:17.263         """
2025-07-02 06:41:17.263
2025-07-02 06:41:17.263         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.263         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.263         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.263         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.263         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.263
2025-07-02 06:41:17.263         # search for the pair that matches best without being identical
2025-07-02 06:41:17.263         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.263         # on junk -- unless we have to)
2025-07-02 06:41:17.263         for j in range(blo, bhi):
2025-07-02 06:41:17.263             bj = b[j]
2025-07-02 06:41:17.263             cruncher.set_seq2(bj)
2025-07-02 06:41:17.263             for i in range(alo, ahi):
2025-07-02 06:41:17.264                 ai = a[i]
2025-07-02 06:41:17.264                 if ai == bj:
2025-07-02 06:41:17.264                     if eqi is None:
2025-07-02 06:41:17.264                         eqi, eqj = i, j
2025-07-02 06:41:17.264                     continue
2025-07-02 06:41:17.264                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.264                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.264                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.264                 # compares by a factor of 3.
2025-07-02 06:41:17.264                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.264                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.264                 # of the computation is cached by cruncher
2025-07-02 06:41:17.264                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.264                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.264                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.264                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.264         if best_ratio < cutoff:
2025-07-02 06:41:17.264             # no non-identical "pretty close" pair
2025-07-02 06:41:17.264             if eqi is None:
2025-07-02 06:41:17.264                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.265                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.265                 return
2025-07-02 06:41:17.265             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.265             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.265         else:
2025-07-02 06:41:17.265             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.265             eqi = None
2025-07-02 06:41:17.265
2025-07-02 06:41:17.265         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.265         # identical
2025-07-02 06:41:17.265
2025-07-02 06:41:17.265         # pump out diffs from before the synch point
2025-07-02 06:41:17.265         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.265
2025-07-02 06:41:17.265         # do intraline marking on the synch pair
2025-07-02 06:41:17.265         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.265         if eqi is None:
2025-07-02 06:41:17.265             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.266             atags = btags = ""
2025-07-02 06:41:17.266             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.266             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.266                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.266                 if tag == 'replace':
2025-07-02 06:41:17.266                     atags += '^' * la
2025-07-02 06:41:17.266                     btags += '^' * lb
2025-07-02 06:41:17.266                 elif tag == 'delete':
2025-07-02 06:41:17.266                     atags += '-' * la
2025-07-02 06:41:17.266                 elif tag == 'insert':
2025-07-02 06:41:17.266                     btags += '+' * lb
2025-07-02 06:41:17.266                 elif tag == 'equal':
2025-07-02 06:41:17.266                     atags += ' ' * la
2025-07-02 06:41:17.266                     btags += ' ' * lb
2025-07-02 06:41:17.266                 else:
2025-07-02 06:41:17.266                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.266             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.266         else:
2025-07-02 06:41:17.266             # the synch pair is identical
2025-07-02 06:41:17.267             yield '  ' + aelt
2025-07-02 06:41:17.267
2025-07-02 06:41:17.267         # pump out diffs from after the synch point
2025-07-02 06:41:17.267 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.267
2025-07-02 06:41:17.267 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.267 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.267
2025-07-02 06:41:17.267 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.267 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.267 alo = 199, ahi = 1101
2025-07-02 06:41:17.267 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.267 blo = 199, bhi = 1101
2025-07-02 06:41:17.267
2025-07-02 06:41:17.267     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.267         g = []
2025-07-02 06:41:17.267         if alo < ahi:
2025-07-02 06:41:17.267             if blo < bhi:
2025-07-02 06:41:17.268                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.268             else:
2025-07-02 06:41:17.268                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.268         elif blo < bhi:
2025-07-02 06:41:17.268             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.268
2025-07-02 06:41:17.268 >       yield from g
2025-07-02 06:41:17.268
2025-07-02 06:41:17.268 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.268 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.268
2025-07-02 06:41:17.268 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.268 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.268 alo = 199, ahi = 1101
2025-07-02 06:41:17.268 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.268 blo = 199, bhi = 1101
2025-07-02 06:41:17.268
2025-07-02 06:41:17.268     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.268         r"""
2025-07-02 06:41:17.268         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.269         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.269         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.269         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.269
2025-07-02 06:41:17.269         Example:
2025-07-02 06:41:17.269
2025-07-02 06:41:17.269         >>> d = Differ()
2025-07-02 06:41:17.269         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.269         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.269         >>> print(''.join(results), end="")
2025-07-02 06:41:17.269         - abcDefghiJkl
2025-07-02 06:41:17.269         + abcdefGhijkl
2025-07-02 06:41:17.269         """
2025-07-02 06:41:17.269
2025-07-02 06:41:17.269         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.269         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.269         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.269         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.270         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.270
2025-07-02 06:41:17.270         # search for the pair that matches best without being identical
2025-07-02 06:41:17.270         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.270         # on junk -- unless we have to)
2025-07-02 06:41:17.270         for j in range(blo, bhi):
2025-07-02 06:41:17.270             bj = b[j]
2025-07-02 06:41:17.270             cruncher.set_seq2(bj)
2025-07-02 06:41:17.270             for i in range(alo, ahi):
2025-07-02 06:41:17.270                 ai = a[i]
2025-07-02 06:41:17.270                 if ai == bj:
2025-07-02 06:41:17.270                     if eqi is None:
2025-07-02 06:41:17.270                         eqi, eqj = i, j
2025-07-02 06:41:17.270                     continue
2025-07-02 06:41:17.270                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.270                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.270                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.270                 # compares by a factor of 3.
2025-07-02 06:41:17.270                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.270                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.270                 # of the computation is cached by cruncher
2025-07-02 06:41:17.271                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.271                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.271                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.271                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.271         if best_ratio < cutoff:
2025-07-02 06:41:17.271             # no non-identical "pretty close" pair
2025-07-02 06:41:17.271             if eqi is None:
2025-07-02 06:41:17.271                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.271                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.271                 return
2025-07-02 06:41:17.271             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.271             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.271         else:
2025-07-02 06:41:17.271             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.271             eqi = None
2025-07-02 06:41:17.271
2025-07-02 06:41:17.271         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.271         # identical
2025-07-02 06:41:17.271
2025-07-02 06:41:17.271         # pump out diffs from before the synch point
2025-07-02 06:41:17.272         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.272
2025-07-02 06:41:17.272         # do intraline marking on the synch pair
2025-07-02 06:41:17.272         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.272         if eqi is None:
2025-07-02 06:41:17.272             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.272             atags = btags = ""
2025-07-02 06:41:17.272             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.272             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.272                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.272                 if tag == 'replace':
2025-07-02 06:41:17.272                     atags += '^' * la
2025-07-02 06:41:17.272                     btags += '^' * lb
2025-07-02 06:41:17.272                 elif tag == 'delete':
2025-07-02 06:41:17.272                     atags += '-' * la
2025-07-02 06:41:17.272                 elif tag == 'insert':
2025-07-02 06:41:17.272                     btags += '+' * lb
2025-07-02 06:41:17.272                 elif tag == 'equal':
2025-07-02 06:41:17.272                     atags += ' ' * la
2025-07-02 06:41:17.272                     btags += ' ' * lb
2025-07-02 06:41:17.272                 else:
2025-07-02 06:41:17.273                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.273             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.273         else:
2025-07-02 06:41:17.273             # the synch pair is identical
2025-07-02 06:41:17.273             yield '  ' + aelt
2025-07-02 06:41:17.273
2025-07-02 06:41:17.273         # pump out diffs from after the synch point
2025-07-02 06:41:17.273 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.273
2025-07-02 06:41:17.273 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.273 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.273
2025-07-02 06:41:17.273 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.273 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.273 alo = 202, ahi = 1101
2025-07-02 06:41:17.273 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.273 blo = 202, bhi = 1101
2025-07-02 06:41:17.274
2025-07-02 06:41:17.274     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.274         g = []
2025-07-02 06:41:17.274         if alo < ahi:
2025-07-02 06:41:17.274             if blo < bhi:
2025-07-02 06:41:17.274                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.274             else:
2025-07-02 06:41:17.274                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.274         elif blo < bhi:
2025-07-02 06:41:17.274             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.274
2025-07-02 06:41:17.274 >       yield from g
2025-07-02 06:41:17.274
2025-07-02 06:41:17.274 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.274 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.274
2025-07-02 06:41:17.274 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.274 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.274 alo = 202, ahi = 1101
2025-07-02 06:41:17.274 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.275 blo = 202, bhi = 1101
2025-07-02 06:41:17.275
2025-07-02 06:41:17.275     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.275         r"""
2025-07-02 06:41:17.275         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.275         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.275         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.275         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.275
2025-07-02 06:41:17.275         Example:
2025-07-02 06:41:17.275
2025-07-02 06:41:17.275         >>> d = Differ()
2025-07-02 06:41:17.275         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.275         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.275         >>> print(''.join(results), end="")
2025-07-02 06:41:17.275         - abcDefghiJkl
2025-07-02 06:41:17.276         + abcdefGhijkl
2025-07-02 06:41:17.276         """
2025-07-02 06:41:17.276
2025-07-02 06:41:17.276         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.276         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.276         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.276         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.276         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.276
2025-07-02 06:41:17.276         # search for the pair that matches best without being identical
2025-07-02 06:41:17.276         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.276         # on junk -- unless we have to)
2025-07-02 06:41:17.276         for j in range(blo, bhi):
2025-07-02 06:41:17.276             bj = b[j]
2025-07-02 06:41:17.276             cruncher.set_seq2(bj)
2025-07-02 06:41:17.276             for i in range(alo, ahi):
2025-07-02 06:41:17.276                 ai = a[i]
2025-07-02 06:41:17.276                 if ai == bj:
2025-07-02 06:41:17.276                     if eqi is None:
2025-07-02 06:41:17.276                         eqi, eqj = i, j
2025-07-02 06:41:17.277                     continue
2025-07-02 06:41:17.277                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.277                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.277                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.277                 # compares by a factor of 3.
2025-07-02 06:41:17.277                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.277                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.277                 # of the computation is cached by cruncher
2025-07-02 06:41:17.277                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.277                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.277                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.277                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.277         if best_ratio < cutoff:
2025-07-02 06:41:17.277             # no non-identical "pretty close" pair
2025-07-02 06:41:17.277             if eqi is None:
2025-07-02 06:41:17.277                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.277                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.277                 return
2025-07-02 06:41:17.277             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.277             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.278         else:
2025-07-02 06:41:17.278             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.278             eqi = None
2025-07-02 06:41:17.278
2025-07-02 06:41:17.278         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.278         # identical
2025-07-02 06:41:17.278
2025-07-02 06:41:17.278         # pump out diffs from before the synch point
2025-07-02 06:41:17.278         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.278
2025-07-02 06:41:17.278         # do intraline marking on the synch pair
2025-07-02 06:41:17.278         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.278         if eqi is None:
2025-07-02 06:41:17.278             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.278             atags = btags = ""
2025-07-02 06:41:17.278             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.278             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.278                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.278                 if tag == 'replace':
2025-07-02 06:41:17.278                     atags += '^' * la
2025-07-02 06:41:17.278                     btags += '^' * lb
2025-07-02 06:41:17.279                 elif tag == 'delete':
2025-07-02 06:41:17.279                     atags += '-' * la
2025-07-02 06:41:17.279                 elif tag == 'insert':
2025-07-02 06:41:17.279                     btags += '+' * lb
2025-07-02 06:41:17.279                 elif tag == 'equal':
2025-07-02 06:41:17.279                     atags += ' ' * la
2025-07-02 06:41:17.279                     btags += ' ' * lb
2025-07-02 06:41:17.279                 else:
2025-07-02 06:41:17.279                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.279             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.279         else:
2025-07-02 06:41:17.279             # the synch pair is identical
2025-07-02 06:41:17.279             yield '  ' + aelt
2025-07-02 06:41:17.279
2025-07-02 06:41:17.279         # pump out diffs from after the synch point
2025-07-02 06:41:17.279 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.279
2025-07-02 06:41:17.279 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.279 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.279
2025-07-02 06:41:17.280 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.280 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.280 alo = 203, ahi = 1101
2025-07-02 06:41:17.280 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.280 blo = 203, bhi = 1101
2025-07-02 06:41:17.280
2025-07-02 06:41:17.280     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.280         g = []
2025-07-02 06:41:17.280         if alo < ahi:
2025-07-02 06:41:17.280             if blo < bhi:
2025-07-02 06:41:17.280                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.280             else:
2025-07-02 06:41:17.280                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.280         elif blo < bhi:
2025-07-02 06:41:17.280             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.280
2025-07-02 06:41:17.280 >       yield from g
2025-07-02 06:41:17.280
2025-07-02 06:41:17.280 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.280 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.281
2025-07-02 06:41:17.281 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.281 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.281 alo = 203, ahi = 1101
2025-07-02 06:41:17.281 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.281 blo = 203, bhi = 1101
2025-07-02 06:41:17.281
2025-07-02 06:41:17.281     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.281         r"""
2025-07-02 06:41:17.281         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.281         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.281         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.281         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.281
2025-07-02 06:41:17.281         Example:
2025-07-02 06:41:17.281
2025-07-02 06:41:17.281         >>> d = Differ()
2025-07-02 06:41:17.281         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.281         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.281         >>> print(''.join(results), end="")
2025-07-02 06:41:17.281         - abcDefghiJkl
2025-07-02 06:41:17.282         + abcdefGhijkl
2025-07-02 06:41:17.282         """
2025-07-02 06:41:17.282
2025-07-02 06:41:17.282         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.282         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.282         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.282         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.282         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.282
2025-07-02 06:41:17.282         # search for the pair that matches best without being identical
2025-07-02 06:41:17.282         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.282         # on junk -- unless we have to)
2025-07-02 06:41:17.282         for j in range(blo, bhi):
2025-07-02 06:41:17.282             bj = b[j]
2025-07-02 06:41:17.282             cruncher.set_seq2(bj)
2025-07-02 06:41:17.282             for i in range(alo, ahi):
2025-07-02 06:41:17.282                 ai = a[i]
2025-07-02 06:41:17.283                 if ai == bj:
2025-07-02 06:41:17.283                     if eqi is None:
2025-07-02 06:41:17.283                         eqi, eqj = i, j
2025-07-02 06:41:17.283                     continue
2025-07-02 06:41:17.283                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.283                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.283                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.283                 # compares by a factor of 3.
2025-07-02 06:41:17.283                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.283                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.283                 # of the computation is cached by cruncher
2025-07-02 06:41:17.283                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.283                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.283                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.283                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.283         if best_ratio < cutoff:
2025-07-02 06:41:17.283             # no non-identical "pretty close" pair
2025-07-02 06:41:17.283             if eqi is None:
2025-07-02 06:41:17.283                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.284                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.284                 return
2025-07-02 06:41:17.284             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.284             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.284         else:
2025-07-02 06:41:17.284             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.284             eqi = None
2025-07-02 06:41:17.284
2025-07-02 06:41:17.284         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.284         # identical
2025-07-02 06:41:17.284
2025-07-02 06:41:17.284         # pump out diffs from before the synch point
2025-07-02 06:41:17.284         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.284
2025-07-02 06:41:17.284         # do intraline marking on the synch pair
2025-07-02 06:41:17.284         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.284         if eqi is None:
2025-07-02 06:41:17.284             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.284             atags = btags = ""
2025-07-02 06:41:17.285             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.285             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.285                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.285                 if tag == 'replace':
2025-07-02 06:41:17.285                     atags += '^' * la
2025-07-02 06:41:17.285                     btags += '^' * lb
2025-07-02 06:41:17.285                 elif tag == 'delete':
2025-07-02 06:41:17.285                     atags += '-' * la
2025-07-02 06:41:17.285                 elif tag == 'insert':
2025-07-02 06:41:17.285                     btags += '+' * lb
2025-07-02 06:41:17.285                 elif tag == 'equal':
2025-07-02 06:41:17.285                     atags += ' ' * la
2025-07-02 06:41:17.285                     btags += ' ' * lb
2025-07-02 06:41:17.285                 else:
2025-07-02 06:41:17.285                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.285             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.285         else:
2025-07-02 06:41:17.285             # the synch pair is identical
2025-07-02 06:41:17.285             yield '  ' + aelt
2025-07-02 06:41:17.285
2025-07-02 06:41:17.285         # pump out diffs from after the synch point
2025-07-02 06:41:17.286 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.286
2025-07-02 06:41:17.286 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.286 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.286
2025-07-02 06:41:17.286 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.286 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.286 alo = 204, ahi = 1101
2025-07-02 06:41:17.286 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.286 blo = 204, bhi = 1101
2025-07-02 06:41:17.286
2025-07-02 06:41:17.286     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.286         g = []
2025-07-02 06:41:17.286         if alo < ahi:
2025-07-02 06:41:17.286             if blo < bhi:
2025-07-02 06:41:17.286                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.286             else:
2025-07-02 06:41:17.286                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.286         elif blo < bhi:
2025-07-02 06:41:17.286             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287 >       yield from g
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.287 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.287 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.287 alo = 204, ahi = 1101
2025-07-02 06:41:17.287 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.287 blo = 204, bhi = 1101
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.287         r"""
2025-07-02 06:41:17.287         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.287         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.287         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.287         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.287
2025-07-02 06:41:17.287         Example:
2025-07-02 06:41:17.288
2025-07-02 06:41:17.288         >>> d = Differ()
2025-07-02 06:41:17.288         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.288         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.288         >>> print(''.join(results), end="")
2025-07-02 06:41:17.288         - abcDefghiJkl
2025-07-02 06:41:17.288         + abcdefGhijkl
2025-07-02 06:41:17.288         """
2025-07-02 06:41:17.288
2025-07-02 06:41:17.288         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.288         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.288         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.288         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.288         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.288
2025-07-02 06:41:17.288         # search for the pair that matches best without being identical
2025-07-02 06:41:17.288         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.288         # on junk -- unless we have to)
2025-07-02 06:41:17.289         for j in range(blo, bhi):
2025-07-02 06:41:17.289             bj = b[j]
2025-07-02 06:41:17.289             cruncher.set_seq2(bj)
2025-07-02 06:41:17.289             for i in range(alo, ahi):
2025-07-02 06:41:17.289                 ai = a[i]
2025-07-02 06:41:17.289                 if ai == bj:
2025-07-02 06:41:17.289                     if eqi is None:
2025-07-02 06:41:17.289                         eqi, eqj = i, j
2025-07-02 06:41:17.289                     continue
2025-07-02 06:41:17.289                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.289                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.289                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.289                 # compares by a factor of 3.
2025-07-02 06:41:17.289                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.289                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.289                 # of the computation is cached by cruncher
2025-07-02 06:41:17.289                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.289                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.289                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.289                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.290         if best_ratio < cutoff:
2025-07-02 06:41:17.290             # no non-identical "pretty close" pair
2025-07-02 06:41:17.290             if eqi is None:
2025-07-02 06:41:17.290                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.290                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.290                 return
2025-07-02 06:41:17.290             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.290             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.290         else:
2025-07-02 06:41:17.290             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.290             eqi = None
2025-07-02 06:41:17.290
2025-07-02 06:41:17.290         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.290         # identical
2025-07-02 06:41:17.290
2025-07-02 06:41:17.290         # pump out diffs from before the synch point
2025-07-02 06:41:17.290         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.290
2025-07-02 06:41:17.290         # do intraline marking on the synch pair
2025-07-02 06:41:17.290         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.291         if eqi is None:
2025-07-02 06:41:17.291             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.291             atags = btags = ""
2025-07-02 06:41:17.291             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.291             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.291                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.291                 if tag == 'replace':
2025-07-02 06:41:17.291                     atags += '^' * la
2025-07-02 06:41:17.291                     btags += '^' * lb
2025-07-02 06:41:17.291                 elif tag == 'delete':
2025-07-02 06:41:17.291                     atags += '-' * la
2025-07-02 06:41:17.291                 elif tag == 'insert':
2025-07-02 06:41:17.291                     btags += '+' * lb
2025-07-02 06:41:17.291                 elif tag == 'equal':
2025-07-02 06:41:17.291                     atags += ' ' * la
2025-07-02 06:41:17.291                     btags += ' ' * lb
2025-07-02 06:41:17.291                 else:
2025-07-02 06:41:17.291                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.292             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.292         else:
2025-07-02 06:41:17.292             # the synch pair is identical
2025-07-02 06:41:17.292             yield '  ' + aelt
2025-07-02 06:41:17.292
2025-07-02 06:41:17.292         # pump out diffs from after the synch point
2025-07-02 06:41:17.292 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.292
2025-07-02 06:41:17.292 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.292 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.292
2025-07-02 06:41:17.292 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.292 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.292 alo = 205, ahi = 1101
2025-07-02 06:41:17.292 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.292 blo = 205, bhi = 1101
2025-07-02 06:41:17.292
2025-07-02 06:41:17.292     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.292         g = []
2025-07-02 06:41:17.293         if alo < ahi:
2025-07-02 06:41:17.293             if blo < bhi:
2025-07-02 06:41:17.293                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.293             else:
2025-07-02 06:41:17.293                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.293         elif blo < bhi:
2025-07-02 06:41:17.293             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.293
2025-07-02 06:41:17.293 >       yield from g
2025-07-02 06:41:17.293
2025-07-02 06:41:17.293 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.293 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.293
2025-07-02 06:41:17.293 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.293 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.293 alo = 205, ahi = 1101
2025-07-02 06:41:17.293 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.293 blo = 205, bhi = 1101
2025-07-02 06:41:17.293
2025-07-02 06:41:17.293     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.294         r"""
2025-07-02 06:41:17.294         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.294         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.294         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.294         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.294
2025-07-02 06:41:17.294         Example:
2025-07-02 06:41:17.294
2025-07-02 06:41:17.294         >>> d = Differ()
2025-07-02 06:41:17.294         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.294         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.294         >>> print(''.join(results), end="")
2025-07-02 06:41:17.294         - abcDefghiJkl
2025-07-02 06:41:17.294         + abcdefGhijkl
2025-07-02 06:41:17.294         """
2025-07-02 06:41:17.294
2025-07-02 06:41:17.294         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.294         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.295         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.295         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.295         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.295
2025-07-02 06:41:17.295         # search for the pair that matches best without being identical
2025-07-02 06:41:17.295         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.295         # on junk -- unless we have to)
2025-07-02 06:41:17.295         for j in range(blo, bhi):
2025-07-02 06:41:17.295             bj = b[j]
2025-07-02 06:41:17.295             cruncher.set_seq2(bj)
2025-07-02 06:41:17.295             for i in range(alo, ahi):
2025-07-02 06:41:17.295                 ai = a[i]
2025-07-02 06:41:17.295                 if ai == bj:
2025-07-02 06:41:17.295                     if eqi is None:
2025-07-02 06:41:17.295                         eqi, eqj = i, j
2025-07-02 06:41:17.295                     continue
2025-07-02 06:41:17.295                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.295                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.295                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.295                 # compares by a factor of 3.
2025-07-02 06:41:17.295                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.296                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.296                 # of the computation is cached by cruncher
2025-07-02 06:41:17.296                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.296                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.296                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.296                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.296         if best_ratio < cutoff:
2025-07-02 06:41:17.296             # no non-identical "pretty close" pair
2025-07-02 06:41:17.296             if eqi is None:
2025-07-02 06:41:17.296                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.296                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.296                 return
2025-07-02 06:41:17.296             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.296             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.296         else:
2025-07-02 06:41:17.296             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.296             eqi = None
2025-07-02 06:41:17.296
2025-07-02 06:41:17.296         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.296         # identical
2025-07-02 06:41:17.297
2025-07-02 06:41:17.297         # pump out diffs from before the synch point
2025-07-02 06:41:17.297         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.297
2025-07-02 06:41:17.297         # do intraline marking on the synch pair
2025-07-02 06:41:17.297         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.297         if eqi is None:
2025-07-02 06:41:17.297             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.297             atags = btags = ""
2025-07-02 06:41:17.297             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.297             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.297                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.297                 if tag == 'replace':
2025-07-02 06:41:17.297                     atags += '^' * la
2025-07-02 06:41:17.297                     btags += '^' * lb
2025-07-02 06:41:17.297                 elif tag == 'delete':
2025-07-02 06:41:17.297                     atags += '-' * la
2025-07-02 06:41:17.297                 elif tag == 'insert':
2025-07-02 06:41:17.297                     btags += '+' * lb
2025-07-02 06:41:17.297                 elif tag == 'equal':
2025-07-02 06:41:17.298                     atags += ' ' * la
2025-07-02 06:41:17.298                     btags += ' ' * lb
2025-07-02 06:41:17.298                 else:
2025-07-02 06:41:17.298                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.298             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.298         else:
2025-07-02 06:41:17.298             # the synch pair is identical
2025-07-02 06:41:17.298             yield '  ' + aelt
2025-07-02 06:41:17.298
2025-07-02 06:41:17.298         # pump out diffs from after the synch point
2025-07-02 06:41:17.298 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.298
2025-07-02 06:41:17.298 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.298 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.298
2025-07-02 06:41:17.298 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.298 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.298 alo = 206, ahi = 1101
2025-07-02 06:41:17.298 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.298 blo = 206, bhi = 1101
2025-07-02 06:41:17.299
2025-07-02 06:41:17.299     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.299         g = []
2025-07-02 06:41:17.299         if alo < ahi:
2025-07-02 06:41:17.299             if blo < bhi:
2025-07-02 06:41:17.299                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.299             else:
2025-07-02 06:41:17.299                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.299         elif blo < bhi:
2025-07-02 06:41:17.299             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.299
2025-07-02 06:41:17.299 >       yield from g
2025-07-02 06:41:17.299
2025-07-02 06:41:17.299 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.299 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.299
2025-07-02 06:41:17.299 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.299 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.300 alo = 206, ahi = 1101
2025-07-02 06:41:17.300 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.300 blo = 206, bhi = 1101
2025-07-02 06:41:17.300
2025-07-02 06:41:17.300     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.300         r"""
2025-07-02 06:41:17.300         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.300         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.300         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.300         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.300
2025-07-02 06:41:17.300         Example:
2025-07-02 06:41:17.300
2025-07-02 06:41:17.300         >>> d = Differ()
2025-07-02 06:41:17.300         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.300         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.300         >>> print(''.join(results), end="")
2025-07-02 06:41:17.300         - abcDefghiJkl
2025-07-02 06:41:17.301         + abcdefGhijkl
2025-07-02 06:41:17.301         """
2025-07-02 06:41:17.301
2025-07-02 06:41:17.301         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.301         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.301         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.301         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.301         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.301
2025-07-02 06:41:17.301         # search for the pair that matches best without being identical
2025-07-02 06:41:17.301         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.301         # on junk -- unless we have to)
2025-07-02 06:41:17.301         for j in range(blo, bhi):
2025-07-02 06:41:17.301             bj = b[j]
2025-07-02 06:41:17.301             cruncher.set_seq2(bj)
2025-07-02 06:41:17.301             for i in range(alo, ahi):
2025-07-02 06:41:17.301                 ai = a[i]
2025-07-02 06:41:17.301                 if ai == bj:
2025-07-02 06:41:17.301                     if eqi is None:
2025-07-02 06:41:17.302                         eqi, eqj = i, j
2025-07-02 06:41:17.302                     continue
2025-07-02 06:41:17.302                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.302                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.302                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.302                 # compares by a factor of 3.
2025-07-02 06:41:17.302                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.302                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.302                 # of the computation is cached by cruncher
2025-07-02 06:41:17.302                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.302                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.302                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.302                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.302         if best_ratio < cutoff:
2025-07-02 06:41:17.302             # no non-identical "pretty close" pair
2025-07-02 06:41:17.302             if eqi is None:
2025-07-02 06:41:17.302                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.302                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.302                 return
2025-07-02 06:41:17.302             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.303             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.303         else:
2025-07-02 06:41:17.303             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.303             eqi = None
2025-07-02 06:41:17.303
2025-07-02 06:41:17.303         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.303         # identical
2025-07-02 06:41:17.303
2025-07-02 06:41:17.303         # pump out diffs from before the synch point
2025-07-02 06:41:17.303         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.303
2025-07-02 06:41:17.303         # do intraline marking on the synch pair
2025-07-02 06:41:17.303         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.303         if eqi is None:
2025-07-02 06:41:17.303             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.303             atags = btags = ""
2025-07-02 06:41:17.303             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.303             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.303                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.303                 if tag == 'replace':
2025-07-02 06:41:17.303                     atags += '^' * la
2025-07-02 06:41:17.304                     btags += '^' * lb
2025-07-02 06:41:17.304                 elif tag == 'delete':
2025-07-02 06:41:17.304                     atags += '-' * la
2025-07-02 06:41:17.304                 elif tag == 'insert':
2025-07-02 06:41:17.304                     btags += '+' * lb
2025-07-02 06:41:17.304                 elif tag == 'equal':
2025-07-02 06:41:17.304                     atags += ' ' * la
2025-07-02 06:41:17.304                     btags += ' ' * lb
2025-07-02 06:41:17.304                 else:
2025-07-02 06:41:17.304                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.304             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.304         else:
2025-07-02 06:41:17.304             # the synch pair is identical
2025-07-02 06:41:17.304             yield '  ' + aelt
2025-07-02 06:41:17.304
2025-07-02 06:41:17.304         # pump out diffs from after the synch point
2025-07-02 06:41:17.304 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.304
2025-07-02 06:41:17.304 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.304 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.304
2025-07-02 06:41:17.305 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.305 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.305 alo = 207, ahi = 1101
2025-07-02 06:41:17.305 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.305 blo = 207, bhi = 1101
2025-07-02 06:41:17.305
2025-07-02 06:41:17.305     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.305         g = []
2025-07-02 06:41:17.305         if alo < ahi:
2025-07-02 06:41:17.305             if blo < bhi:
2025-07-02 06:41:17.305                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.305             else:
2025-07-02 06:41:17.305                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.305         elif blo < bhi:
2025-07-02 06:41:17.305             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.305
2025-07-02 06:41:17.305 >       yield from g
2025-07-02 06:41:17.305
2025-07-02 06:41:17.305 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.305 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.306
2025-07-02 06:41:17.306 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.306 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.306 alo = 207, ahi = 1101
2025-07-02 06:41:17.306 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.306 blo = 207, bhi = 1101
2025-07-02 06:41:17.306
2025-07-02 06:41:17.306     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.306         r"""
2025-07-02 06:41:17.306         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.306         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.306         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.306         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.306
2025-07-02 06:41:17.306         Example:
2025-07-02 06:41:17.306
2025-07-02 06:41:17.306         >>> d = Differ()
2025-07-02 06:41:17.306         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.306         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.306         >>> print(''.join(results), end="")
2025-07-02 06:41:17.307         - abcDefghiJkl
2025-07-02 06:41:17.307         + abcdefGhijkl
2025-07-02 06:41:17.307         """
2025-07-02 06:41:17.307
2025-07-02 06:41:17.307         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.307         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.307         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.307         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.307         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.307
2025-07-02 06:41:17.307         # search for the pair that matches best without being identical
2025-07-02 06:41:17.307         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.307         # on junk -- unless we have to)
2025-07-02 06:41:17.307         for j in range(blo, bhi):
2025-07-02 06:41:17.307             bj = b[j]
2025-07-02 06:41:17.307             cruncher.set_seq2(bj)
2025-07-02 06:41:17.307             for i in range(alo, ahi):
2025-07-02 06:41:17.307                 ai = a[i]
2025-07-02 06:41:17.307                 if ai == bj:
2025-07-02 06:41:17.308                     if eqi is None:
2025-07-02 06:41:17.308                         eqi, eqj = i, j
2025-07-02 06:41:17.308                     continue
2025-07-02 06:41:17.308                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.308                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.308                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.308                 # compares by a factor of 3.
2025-07-02 06:41:17.308                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.308                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.308                 # of the computation is cached by cruncher
2025-07-02 06:41:17.308                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.308                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.308                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.308                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.308         if best_ratio < cutoff:
2025-07-02 06:41:17.308             # no non-identical "pretty close" pair
2025-07-02 06:41:17.308             if eqi is None:
2025-07-02 06:41:17.308                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.308                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.309                 return
2025-07-02 06:41:17.309             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.309             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.309         else:
2025-07-02 06:41:17.309             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.309             eqi = None
2025-07-02 06:41:17.309
2025-07-02 06:41:17.309         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.309         # identical
2025-07-02 06:41:17.309
2025-07-02 06:41:17.309         # pump out diffs from before the synch point
2025-07-02 06:41:17.309         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.309
2025-07-02 06:41:17.309         # do intraline marking on the synch pair
2025-07-02 06:41:17.309         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.309         if eqi is None:
2025-07-02 06:41:17.309             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.309             atags = btags = ""
2025-07-02 06:41:17.309             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.309             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.310                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.310                 if tag == 'replace':
2025-07-02 06:41:17.310                     atags += '^' * la
2025-07-02 06:41:17.310                     btags += '^' * lb
2025-07-02 06:41:17.310                 elif tag == 'delete':
2025-07-02 06:41:17.310                     atags += '-' * la
2025-07-02 06:41:17.310                 elif tag == 'insert':
2025-07-02 06:41:17.310                     btags += '+' * lb
2025-07-02 06:41:17.310                 elif tag == 'equal':
2025-07-02 06:41:17.310                     atags += ' ' * la
2025-07-02 06:41:17.310                     btags += ' ' * lb
2025-07-02 06:41:17.310                 else:
2025-07-02 06:41:17.310                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.310             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.310         else:
2025-07-02 06:41:17.310             # the synch pair is identical
2025-07-02 06:41:17.310             yield '  ' + aelt
2025-07-02 06:41:17.310
2025-07-02 06:41:17.310         # pump out diffs from after the synch point
2025-07-02 06:41:17.310 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.311
2025-07-02 06:41:17.311 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.311 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.311
2025-07-02 06:41:17.311 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.311 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.311 alo = 208, ahi = 1101
2025-07-02 06:41:17.311 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.311 blo = 208, bhi = 1101
2025-07-02 06:41:17.311
2025-07-02 06:41:17.311     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.311         g = []
2025-07-02 06:41:17.311         if alo < ahi:
2025-07-02 06:41:17.311             if blo < bhi:
2025-07-02 06:41:17.311                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.311             else:
2025-07-02 06:41:17.311                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.311         elif blo < bhi:
2025-07-02 06:41:17.311             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.311
2025-07-02 06:41:17.312 >       yield from g
2025-07-02 06:41:17.312
2025-07-02 06:41:17.312 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.312 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.312
2025-07-02 06:41:17.312 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.312 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.312 alo = 208, ahi = 1101
2025-07-02 06:41:17.312 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.312 blo = 208, bhi = 1101
2025-07-02 06:41:17.312
2025-07-02 06:41:17.312     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.312         r"""
2025-07-02 06:41:17.312         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.312         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.312         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.312         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.312
2025-07-02 06:41:17.312         Example:
2025-07-02 06:41:17.312
2025-07-02 06:41:17.313         >>> d = Differ()
2025-07-02 06:41:17.313         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.313         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.313         >>> print(''.join(results), end="")
2025-07-02 06:41:17.313         - abcDefghiJkl
2025-07-02 06:41:17.313         + abcdefGhijkl
2025-07-02 06:41:17.313         """
2025-07-02 06:41:17.313
2025-07-02 06:41:17.313         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.313         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.313         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.313         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.313         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.313
2025-07-02 06:41:17.313         # search for the pair that matches best without being identical
2025-07-02 06:41:17.313         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.313         # on junk -- unless we have to)
2025-07-02 06:41:17.313         for j in range(blo, bhi):
2025-07-02 06:41:17.313             bj = b[j]
2025-07-02 06:41:17.314             cruncher.set_seq2(bj)
2025-07-02 06:41:17.314             for i in range(alo, ahi):
2025-07-02 06:41:17.314                 ai = a[i]
2025-07-02 06:41:17.314                 if ai == bj:
2025-07-02 06:41:17.314                     if eqi is None:
2025-07-02 06:41:17.314                         eqi, eqj = i, j
2025-07-02 06:41:17.314                     continue
2025-07-02 06:41:17.314                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.314                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.314                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.314                 # compares by a factor of 3.
2025-07-02 06:41:17.314                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.314                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.314                 # of the computation is cached by cruncher
2025-07-02 06:41:17.314                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.314                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.314                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.314                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.314         if best_ratio < cutoff:
2025-07-02 06:41:17.314             # no non-identical "pretty close" pair
2025-07-02 06:41:17.314             if eqi is None:
2025-07-02 06:41:17.315                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.315                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.315                 return
2025-07-02 06:41:17.315             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.315             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.315         else:
2025-07-02 06:41:17.315             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.315             eqi = None
2025-07-02 06:41:17.315
2025-07-02 06:41:17.315         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.315         # identical
2025-07-02 06:41:17.315
2025-07-02 06:41:17.315         # pump out diffs from before the synch point
2025-07-02 06:41:17.315         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.315
2025-07-02 06:41:17.315         # do intraline marking on the synch pair
2025-07-02 06:41:17.315         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.315         if eqi is None:
2025-07-02 06:41:17.316             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.316             atags = btags = ""
2025-07-02 06:41:17.316             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.316             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.316                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.316                 if tag == 'replace':
2025-07-02 06:41:17.316                     atags += '^' * la
2025-07-02 06:41:17.316                     btags += '^' * lb
2025-07-02 06:41:17.316                 elif tag == 'delete':
2025-07-02 06:41:17.316                     atags += '-' * la
2025-07-02 06:41:17.316                 elif tag == 'insert':
2025-07-02 06:41:17.316                     btags += '+' * lb
2025-07-02 06:41:17.316                 elif tag == 'equal':
2025-07-02 06:41:17.316                     atags += ' ' * la
2025-07-02 06:41:17.316                     btags += ' ' * lb
2025-07-02 06:41:17.316                 else:
2025-07-02 06:41:17.316                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.316             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.316         else:
2025-07-02 06:41:17.316             # the synch pair is identical
2025-07-02 06:41:17.317             yield '  ' + aelt
2025-07-02 06:41:17.317
2025-07-02 06:41:17.317         # pump out diffs from after the synch point
2025-07-02 06:41:17.317 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.317
2025-07-02 06:41:17.317 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.317 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.317
2025-07-02 06:41:17.317 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.317 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.317 alo = 209, ahi = 1101
2025-07-02 06:41:17.317 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.317 blo = 209, bhi = 1101
2025-07-02 06:41:17.317
2025-07-02 06:41:17.317     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.317         g = []
2025-07-02 06:41:17.317         if alo < ahi:
2025-07-02 06:41:17.318             if blo < bhi:
2025-07-02 06:41:17.318                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.318             else:
2025-07-02 06:41:17.318                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.318         elif blo < bhi:
2025-07-02 06:41:17.318             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.318
2025-07-02 06:41:17.318 >       yield from g
2025-07-02 06:41:17.318
2025-07-02 06:41:17.318 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.318 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.318
2025-07-02 06:41:17.318 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.318 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.318 alo = 209, ahi = 1101
2025-07-02 06:41:17.318 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.318 blo = 209, bhi = 1101
2025-07-02 06:41:17.318
2025-07-02 06:41:17.318     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.319         r"""
2025-07-02 06:41:17.319         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.319         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.319         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.319         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.319
2025-07-02 06:41:17.319         Example:
2025-07-02 06:41:17.319
2025-07-02 06:41:17.319         >>> d = Differ()
2025-07-02 06:41:17.319         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.319         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.319         >>> print(''.join(results), end="")
2025-07-02 06:41:17.319         - abcDefghiJkl
2025-07-02 06:41:17.319         + abcdefGhijkl
2025-07-02 06:41:17.319         """
2025-07-02 06:41:17.319
2025-07-02 06:41:17.319         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.319         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.320         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.320         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.320         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.320
2025-07-02 06:41:17.320         # search for the pair that matches best without being identical
2025-07-02 06:41:17.320         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.320         # on junk -- unless we have to)
2025-07-02 06:41:17.320         for j in range(blo, bhi):
2025-07-02 06:41:17.320             bj = b[j]
2025-07-02 06:41:17.320             cruncher.set_seq2(bj)
2025-07-02 06:41:17.320             for i in range(alo, ahi):
2025-07-02 06:41:17.320                 ai = a[i]
2025-07-02 06:41:17.320                 if ai == bj:
2025-07-02 06:41:17.320                     if eqi is None:
2025-07-02 06:41:17.320                         eqi, eqj = i, j
2025-07-02 06:41:17.320                     continue
2025-07-02 06:41:17.320                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.320                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.320                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.320                 # compares by a factor of 3.
2025-07-02 06:41:17.320                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.321                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.321                 # of the computation is cached by cruncher
2025-07-02 06:41:17.321                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.321                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.321                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.321                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.321         if best_ratio < cutoff:
2025-07-02 06:41:17.321             # no non-identical "pretty close" pair
2025-07-02 06:41:17.321             if eqi is None:
2025-07-02 06:41:17.321                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.321                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.321                 return
2025-07-02 06:41:17.321             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.321             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.321         else:
2025-07-02 06:41:17.321             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.321             eqi = None
2025-07-02 06:41:17.321
2025-07-02 06:41:17.321         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.322         # identical
2025-07-02 06:41:17.322
2025-07-02 06:41:17.322         # pump out diffs from before the synch point
2025-07-02 06:41:17.322         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.322
2025-07-02 06:41:17.322         # do intraline marking on the synch pair
2025-07-02 06:41:17.322         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.322         if eqi is None:
2025-07-02 06:41:17.322             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.322             atags = btags = ""
2025-07-02 06:41:17.322             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.322             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.322                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.322                 if tag == 'replace':
2025-07-02 06:41:17.322                     atags += '^' * la
2025-07-02 06:41:17.322                     btags += '^' * lb
2025-07-02 06:41:17.322                 elif tag == 'delete':
2025-07-02 06:41:17.322                     atags += '-' * la
2025-07-02 06:41:17.322                 elif tag == 'insert':
2025-07-02 06:41:17.322                     btags += '+' * lb
2025-07-02 06:41:17.322                 elif tag == 'equal':
2025-07-02 06:41:17.323                     atags += ' ' * la
2025-07-02 06:41:17.323                     btags += ' ' * lb
2025-07-02 06:41:17.323                 else:
2025-07-02 06:41:17.323                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.323             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.323         else:
2025-07-02 06:41:17.323             # the synch pair is identical
2025-07-02 06:41:17.323             yield '  ' + aelt
2025-07-02 06:41:17.323
2025-07-02 06:41:17.323         # pump out diffs from after the synch point
2025-07-02 06:41:17.323 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.323
2025-07-02 06:41:17.323 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.323 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.323
2025-07-02 06:41:17.323 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.323 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.323 alo = 210, ahi = 1101
2025-07-02 06:41:17.323 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.323 blo = 210, bhi = 1101
2025-07-02 06:41:17.324
2025-07-02 06:41:17.324     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.324         g = []
2025-07-02 06:41:17.324         if alo < ahi:
2025-07-02 06:41:17.324             if blo < bhi:
2025-07-02 06:41:17.324                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.324             else:
2025-07-02 06:41:17.324                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.324         elif blo < bhi:
2025-07-02 06:41:17.324             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.324
2025-07-02 06:41:17.324 >       yield from g
2025-07-02 06:41:17.324
2025-07-02 06:41:17.324 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.324 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.324
2025-07-02 06:41:17.324 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.324 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.324 alo = 210, ahi = 1101
2025-07-02 06:41:17.324 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.325 blo = 210, bhi = 1101
2025-07-02 06:41:17.325
2025-07-02 06:41:17.325     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.325         r"""
2025-07-02 06:41:17.325         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.325         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.325         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.325         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.325
2025-07-02 06:41:17.325         Example:
2025-07-02 06:41:17.325
2025-07-02 06:41:17.325         >>> d = Differ()
2025-07-02 06:41:17.325         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.325         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.325         >>> print(''.join(results), end="")
2025-07-02 06:41:17.325         - abcDefghiJkl
2025-07-02 06:41:17.325         + abcdefGhijkl
2025-07-02 06:41:17.326         """
2025-07-02 06:41:17.326
2025-07-02 06:41:17.326         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.326         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.326         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.326         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.326         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.326
2025-07-02 06:41:17.326         # search for the pair that matches best without being identical
2025-07-02 06:41:17.326         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.326         # on junk -- unless we have to)
2025-07-02 06:41:17.326         for j in range(blo, bhi):
2025-07-02 06:41:17.326             bj = b[j]
2025-07-02 06:41:17.326             cruncher.set_seq2(bj)
2025-07-02 06:41:17.326             for i in range(alo, ahi):
2025-07-02 06:41:17.326                 ai = a[i]
2025-07-02 06:41:17.326                 if ai == bj:
2025-07-02 06:41:17.326                     if eqi is None:
2025-07-02 06:41:17.327                         eqi, eqj = i, j
2025-07-02 06:41:17.327                     continue
2025-07-02 06:41:17.327                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.327                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.327                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.327                 # compares by a factor of 3.
2025-07-02 06:41:17.327                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.327                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.327                 # of the computation is cached by cruncher
2025-07-02 06:41:17.327                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.327                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.327                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.327                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.327         if best_ratio < cutoff:
2025-07-02 06:41:17.327             # no non-identical "pretty close" pair
2025-07-02 06:41:17.327             if eqi is None:
2025-07-02 06:41:17.327                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.327                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.327                 return
2025-07-02 06:41:17.327             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.328             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.328         else:
2025-07-02 06:41:17.328             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.328             eqi = None
2025-07-02 06:41:17.328
2025-07-02 06:41:17.328         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.328         # identical
2025-07-02 06:41:17.328
2025-07-02 06:41:17.328         # pump out diffs from before the synch point
2025-07-02 06:41:17.328         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.328
2025-07-02 06:41:17.328         # do intraline marking on the synch pair
2025-07-02 06:41:17.328         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.328         if eqi is None:
2025-07-02 06:41:17.328             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.328             atags = btags = ""
2025-07-02 06:41:17.328             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.328             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.328                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.328                 if tag == 'replace':
2025-07-02 06:41:17.329                     atags += '^' * la
2025-07-02 06:41:17.329                     btags += '^' * lb
2025-07-02 06:41:17.329                 elif tag == 'delete':
2025-07-02 06:41:17.329                     atags += '-' * la
2025-07-02 06:41:17.329                 elif tag == 'insert':
2025-07-02 06:41:17.329                     btags += '+' * lb
2025-07-02 06:41:17.329                 elif tag == 'equal':
2025-07-02 06:41:17.329                     atags += ' ' * la
2025-07-02 06:41:17.329                     btags += ' ' * lb
2025-07-02 06:41:17.329                 else:
2025-07-02 06:41:17.329                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.329             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.329         else:
2025-07-02 06:41:17.329             # the synch pair is identical
2025-07-02 06:41:17.329             yield '  ' + aelt
2025-07-02 06:41:17.329
2025-07-02 06:41:17.329         # pump out diffs from after the synch point
2025-07-02 06:41:17.329 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.329
2025-07-02 06:41:17.329 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.329 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.330
2025-07-02 06:41:17.330 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.330 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.330 alo = 211, ahi = 1101
2025-07-02 06:41:17.330 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.330 blo = 211, bhi = 1101
2025-07-02 06:41:17.330
2025-07-02 06:41:17.330     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.330         g = []
2025-07-02 06:41:17.330         if alo < ahi:
2025-07-02 06:41:17.330             if blo < bhi:
2025-07-02 06:41:17.330                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.330             else:
2025-07-02 06:41:17.330                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.330         elif blo < bhi:
2025-07-02 06:41:17.330             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.330
2025-07-02 06:41:17.330 >       yield from g
2025-07-02 06:41:17.330
2025-07-02 06:41:17.330 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.331 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.331
2025-07-02 06:41:17.331 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.331 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.331 alo = 211, ahi = 1101
2025-07-02 06:41:17.331 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.331 blo = 211, bhi = 1101
2025-07-02 06:41:17.331
2025-07-02 06:41:17.331     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.331         r"""
2025-07-02 06:41:17.331         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.331         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.331         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.331         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.331
2025-07-02 06:41:17.331         Example:
2025-07-02 06:41:17.331
2025-07-02 06:41:17.331         >>> d = Differ()
2025-07-02 06:41:17.332         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.332         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.332         >>> print(''.join(results), end="")
2025-07-02 06:41:17.332         - abcDefghiJkl
2025-07-02 06:41:17.332         + abcdefGhijkl
2025-07-02 06:41:17.332         """
2025-07-02 06:41:17.332
2025-07-02 06:41:17.332         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.332         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.332         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.332         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.332         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.332
2025-07-02 06:41:17.332         # search for the pair that matches best without being identical
2025-07-02 06:41:17.332         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.332         # on junk -- unless we have to)
2025-07-02 06:41:17.332         for j in range(blo, bhi):
2025-07-02 06:41:17.332             bj = b[j]
2025-07-02 06:41:17.333             cruncher.set_seq2(bj)
2025-07-02 06:41:17.333             for i in range(alo, ahi):
2025-07-02 06:41:17.333                 ai = a[i]
2025-07-02 06:41:17.333                 if ai == bj:
2025-07-02 06:41:17.333                     if eqi is None:
2025-07-02 06:41:17.333                         eqi, eqj = i, j
2025-07-02 06:41:17.333                     continue
2025-07-02 06:41:17.333                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.333                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.333                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.333                 # compares by a factor of 3.
2025-07-02 06:41:17.333                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.333                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.333                 # of the computation is cached by cruncher
2025-07-02 06:41:17.333                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.333                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.333                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.333                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.333         if best_ratio < cutoff:
2025-07-02 06:41:17.333             # no non-identical "pretty close" pair
2025-07-02 06:41:17.333             if eqi is None:
2025-07-02 06:41:17.334                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.334                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.334                 return
2025-07-02 06:41:17.334             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.334             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.334         else:
2025-07-02 06:41:17.334             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.334             eqi = None
2025-07-02 06:41:17.334
2025-07-02 06:41:17.334         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.334         # identical
2025-07-02 06:41:17.334
2025-07-02 06:41:17.334         # pump out diffs from before the synch point
2025-07-02 06:41:17.334         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.334
2025-07-02 06:41:17.334         # do intraline marking on the synch pair
2025-07-02 06:41:17.334         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.334         if eqi is None:
2025-07-02 06:41:17.335             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.335             atags = btags = ""
2025-07-02 06:41:17.335             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.335             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.335                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.335                 if tag == 'replace':
2025-07-02 06:41:17.335                     atags += '^' * la
2025-07-02 06:41:17.335                     btags += '^' * lb
2025-07-02 06:41:17.335                 elif tag == 'delete':
2025-07-02 06:41:17.335                     atags += '-' * la
2025-07-02 06:41:17.335                 elif tag == 'insert':
2025-07-02 06:41:17.335                     btags += '+' * lb
2025-07-02 06:41:17.335                 elif tag == 'equal':
2025-07-02 06:41:17.335                     atags += ' ' * la
2025-07-02 06:41:17.335                     btags += ' ' * lb
2025-07-02 06:41:17.335                 else:
2025-07-02 06:41:17.335                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.335             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.335         else:
2025-07-02 06:41:17.336             # the synch pair is identical
2025-07-02 06:41:17.336             yield '  ' + aelt
2025-07-02 06:41:17.336
2025-07-02 06:41:17.336         # pump out diffs from after the synch point
2025-07-02 06:41:17.336 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.336
2025-07-02 06:41:17.336 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.336 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.336
2025-07-02 06:41:17.336 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.336 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.336 alo = 212, ahi = 1101
2025-07-02 06:41:17.336 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.336 blo = 212, bhi = 1101
2025-07-02 06:41:17.336
2025-07-02 06:41:17.336     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.336         g = []
2025-07-02 06:41:17.336         if alo < ahi:
2025-07-02 06:41:17.336             if blo < bhi:
2025-07-02 06:41:17.337                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.337             else:
2025-07-02 06:41:17.337                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.337         elif blo < bhi:
2025-07-02 06:41:17.337             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.337
2025-07-02 06:41:17.337 >       yield from g
2025-07-02 06:41:17.337
2025-07-02 06:41:17.337 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.337 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.337
2025-07-02 06:41:17.337 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.337 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.337 alo = 212, ahi = 1101
2025-07-02 06:41:17.337 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.337 blo = 212, bhi = 1101
2025-07-02 06:41:17.337
2025-07-02 06:41:17.337     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.337         r"""
2025-07-02 06:41:17.337         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.338         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.338         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.338         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.338
2025-07-02 06:41:17.338         Example:
2025-07-02 06:41:17.338
2025-07-02 06:41:17.338         >>> d = Differ()
2025-07-02 06:41:17.338         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.338         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.338         >>> print(''.join(results), end="")
2025-07-02 06:41:17.338         - abcDefghiJkl
2025-07-02 06:41:17.338         + abcdefGhijkl
2025-07-02 06:41:17.338         """
2025-07-02 06:41:17.338
2025-07-02 06:41:17.338         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.338         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.338         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.338         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.338         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.339
2025-07-02 06:41:17.339         # search for the pair that matches best without being identical
2025-07-02 06:41:17.339         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.339         # on junk -- unless we have to)
2025-07-02 06:41:17.339         for j in range(blo, bhi):
2025-07-02 06:41:17.339             bj = b[j]
2025-07-02 06:41:17.339             cruncher.set_seq2(bj)
2025-07-02 06:41:17.339             for i in range(alo, ahi):
2025-07-02 06:41:17.339                 ai = a[i]
2025-07-02 06:41:17.339                 if ai == bj:
2025-07-02 06:41:17.339                     if eqi is None:
2025-07-02 06:41:17.339                         eqi, eqj = i, j
2025-07-02 06:41:17.339                     continue
2025-07-02 06:41:17.339                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.339                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.339                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.339                 # compares by a factor of 3.
2025-07-02 06:41:17.339                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.339                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.339                 # of the computation is cached by cruncher
2025-07-02 06:41:17.340                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.340                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.340                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.340                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.340         if best_ratio < cutoff:
2025-07-02 06:41:17.340             # no non-identical "pretty close" pair
2025-07-02 06:41:17.340             if eqi is None:
2025-07-02 06:41:17.340                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.340                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.340                 return
2025-07-02 06:41:17.340             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.340             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.340         else:
2025-07-02 06:41:17.340             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.340             eqi = None
2025-07-02 06:41:17.340
2025-07-02 06:41:17.340         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.340         # identical
2025-07-02 06:41:17.340
2025-07-02 06:41:17.340         # pump out diffs from before the synch point
2025-07-02 06:41:17.340         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.341
2025-07-02 06:41:17.341         # do intraline marking on the synch pair
2025-07-02 06:41:17.341         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.341         if eqi is None:
2025-07-02 06:41:17.341             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.341             atags = btags = ""
2025-07-02 06:41:17.341             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.341             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.341                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.341                 if tag == 'replace':
2025-07-02 06:41:17.341                     atags += '^' * la
2025-07-02 06:41:17.341                     btags += '^' * lb
2025-07-02 06:41:17.341                 elif tag == 'delete':
2025-07-02 06:41:17.341                     atags += '-' * la
2025-07-02 06:41:17.341                 elif tag == 'insert':
2025-07-02 06:41:17.341                     btags += '+' * lb
2025-07-02 06:41:17.341                 elif tag == 'equal':
2025-07-02 06:41:17.341                     atags += ' ' * la
2025-07-02 06:41:17.341                     btags += ' ' * lb
2025-07-02 06:41:17.341                 else:
2025-07-02 06:41:17.342                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.342             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.342         else:
2025-07-02 06:41:17.342             # the synch pair is identical
2025-07-02 06:41:17.342             yield '  ' + aelt
2025-07-02 06:41:17.342
2025-07-02 06:41:17.342         # pump out diffs from after the synch point
2025-07-02 06:41:17.342 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.342
2025-07-02 06:41:17.342 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.342 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.342
2025-07-02 06:41:17.342 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.342 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.342 alo = 213, ahi = 1101
2025-07-02 06:41:17.342 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.342 blo = 213, bhi = 1101
2025-07-02 06:41:17.342
2025-07-02 06:41:17.342     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.342         g = []
2025-07-02 06:41:17.343         if alo < ahi:
2025-07-02 06:41:17.343             if blo < bhi:
2025-07-02 06:41:17.343                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.343             else:
2025-07-02 06:41:17.343                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.343         elif blo < bhi:
2025-07-02 06:41:17.343             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.343
2025-07-02 06:41:17.343 >       yield from g
2025-07-02 06:41:17.343
2025-07-02 06:41:17.343 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.343 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.343
2025-07-02 06:41:17.343 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.343 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.343 alo = 213, ahi = 1101
2025-07-02 06:41:17.343 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.343 blo = 213, bhi = 1101
2025-07-02 06:41:17.344
2025-07-02 06:41:17.344     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.344         r"""
2025-07-02 06:41:17.344         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.344         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.344         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.344         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.344
2025-07-02 06:41:17.344         Example:
2025-07-02 06:41:17.344
2025-07-02 06:41:17.344         >>> d = Differ()
2025-07-02 06:41:17.344         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.344         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.344         >>> print(''.join(results), end="")
2025-07-02 06:41:17.344         - abcDefghiJkl
2025-07-02 06:41:17.344         + abcdefGhijkl
2025-07-02 06:41:17.344         """
2025-07-02 06:41:17.345
2025-07-02 06:41:17.345         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.345         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.345         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.345         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.345         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.345
2025-07-02 06:41:17.345         # search for the pair that matches best without being identical
2025-07-02 06:41:17.345         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.345         # on junk -- unless we have to)
2025-07-02 06:41:17.345         for j in range(blo, bhi):
2025-07-02 06:41:17.345             bj = b[j]
2025-07-02 06:41:17.345             cruncher.set_seq2(bj)
2025-07-02 06:41:17.345             for i in range(alo, ahi):
2025-07-02 06:41:17.345                 ai = a[i]
2025-07-02 06:41:17.345                 if ai == bj:
2025-07-02 06:41:17.345                     if eqi is None:
2025-07-02 06:41:17.345                         eqi, eqj = i, j
2025-07-02 06:41:17.345                     continue
2025-07-02 06:41:17.345                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.345                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.346                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.346                 # compares by a factor of 3.
2025-07-02 06:41:17.346                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.346                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.346                 # of the computation is cached by cruncher
2025-07-02 06:41:17.346                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.346                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.346                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.346                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.346         if best_ratio < cutoff:
2025-07-02 06:41:17.346             # no non-identical "pretty close" pair
2025-07-02 06:41:17.346             if eqi is None:
2025-07-02 06:41:17.346                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.346                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.346                 return
2025-07-02 06:41:17.346             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.346             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.346         else:
2025-07-02 06:41:17.346             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.346             eqi = None
2025-07-02 06:41:17.347
2025-07-02 06:41:17.347         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.347         # identical
2025-07-02 06:41:17.347
2025-07-02 06:41:17.347         # pump out diffs from before the synch point
2025-07-02 06:41:17.347         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.347
2025-07-02 06:41:17.347         # do intraline marking on the synch pair
2025-07-02 06:41:17.347         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.347         if eqi is None:
2025-07-02 06:41:17.347             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.347             atags = btags = ""
2025-07-02 06:41:17.347             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.347             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.347                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.347                 if tag == 'replace':
2025-07-02 06:41:17.347                     atags += '^' * la
2025-07-02 06:41:17.347                     btags += '^' * lb
2025-07-02 06:41:17.347                 elif tag == 'delete':
2025-07-02 06:41:17.348                     atags += '-' * la
2025-07-02 06:41:17.348                 elif tag == 'insert':
2025-07-02 06:41:17.348                     btags += '+' * lb
2025-07-02 06:41:17.348                 elif tag == 'equal':
2025-07-02 06:41:17.348                     atags += ' ' * la
2025-07-02 06:41:17.348                     btags += ' ' * lb
2025-07-02 06:41:17.348                 else:
2025-07-02 06:41:17.348                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.348             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.348         else:
2025-07-02 06:41:17.348             # the synch pair is identical
2025-07-02 06:41:17.348             yield '  ' + aelt
2025-07-02 06:41:17.348
2025-07-02 06:41:17.348         # pump out diffs from after the synch point
2025-07-02 06:41:17.348 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.348
2025-07-02 06:41:17.348 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.348 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.348
2025-07-02 06:41:17.349 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.349 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.349 alo = 214, ahi = 1101
2025-07-02 06:41:17.349 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.349 blo = 214, bhi = 1101
2025-07-02 06:41:17.349
2025-07-02 06:41:17.349     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.349         g = []
2025-07-02 06:41:17.349         if alo < ahi:
2025-07-02 06:41:17.349             if blo < bhi:
2025-07-02 06:41:17.349                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.349             else:
2025-07-02 06:41:17.349                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.349         elif blo < bhi:
2025-07-02 06:41:17.349             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.349
2025-07-02 06:41:17.349 >       yield from g
2025-07-02 06:41:17.349
2025-07-02 06:41:17.349 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.349 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.350
2025-07-02 06:41:17.350 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.350 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.350 alo = 214, ahi = 1101
2025-07-02 06:41:17.350 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.350 blo = 214, bhi = 1101
2025-07-02 06:41:17.350
2025-07-02 06:41:17.350     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.350         r"""
2025-07-02 06:41:17.350         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.350         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.350         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.350         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.350
2025-07-02 06:41:17.350         Example:
2025-07-02 06:41:17.350
2025-07-02 06:41:17.350         >>> d = Differ()
2025-07-02 06:41:17.350         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.350         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.350         >>> print(''.join(results), end="")
2025-07-02 06:41:17.351         - abcDefghiJkl
2025-07-02 06:41:17.351         + abcdefGhijkl
2025-07-02 06:41:17.351         """
2025-07-02 06:41:17.351
2025-07-02 06:41:17.351         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.351         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.351         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.351         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.351         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.351
2025-07-02 06:41:17.351         # search for the pair that matches best without being identical
2025-07-02 06:41:17.351         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.351         # on junk -- unless we have to)
2025-07-02 06:41:17.351         for j in range(blo, bhi):
2025-07-02 06:41:17.351             bj = b[j]
2025-07-02 06:41:17.351             cruncher.set_seq2(bj)
2025-07-02 06:41:17.351             for i in range(alo, ahi):
2025-07-02 06:41:17.351                 ai = a[i]
2025-07-02 06:41:17.352                 if ai == bj:
2025-07-02 06:41:17.352                     if eqi is None:
2025-07-02 06:41:17.352                         eqi, eqj = i, j
2025-07-02 06:41:17.352                     continue
2025-07-02 06:41:17.352                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.352                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.352                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.352                 # compares by a factor of 3.
2025-07-02 06:41:17.352                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.352                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.352                 # of the computation is cached by cruncher
2025-07-02 06:41:17.352                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.352                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.352                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.352                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.352         if best_ratio < cutoff:
2025-07-02 06:41:17.352             # no non-identical "pretty close" pair
2025-07-02 06:41:17.352             if eqi is None:
2025-07-02 06:41:17.353                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.353                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.353                 return
2025-07-02 06:41:17.353             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.353             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.353         else:
2025-07-02 06:41:17.353             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.353             eqi = None
2025-07-02 06:41:17.353
2025-07-02 06:41:17.353         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.353         # identical
2025-07-02 06:41:17.353
2025-07-02 06:41:17.353         # pump out diffs from before the synch point
2025-07-02 06:41:17.353         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.353
2025-07-02 06:41:17.353         # do intraline marking on the synch pair
2025-07-02 06:41:17.353         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.353         if eqi is None:
2025-07-02 06:41:17.353             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.354             atags = btags = ""
2025-07-02 06:41:17.354             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.354             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.354                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.354                 if tag == 'replace':
2025-07-02 06:41:17.354                     atags += '^' * la
2025-07-02 06:41:17.354                     btags += '^' * lb
2025-07-02 06:41:17.354                 elif tag == 'delete':
2025-07-02 06:41:17.354                     atags += '-' * la
2025-07-02 06:41:17.354                 elif tag == 'insert':
2025-07-02 06:41:17.354                     btags += '+' * lb
2025-07-02 06:41:17.354                 elif tag == 'equal':
2025-07-02 06:41:17.354                     atags += ' ' * la
2025-07-02 06:41:17.354                     btags += ' ' * lb
2025-07-02 06:41:17.354                 else:
2025-07-02 06:41:17.354                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.354             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.355         else:
2025-07-02 06:41:17.355             # the synch pair is identical
2025-07-02 06:41:17.355             yield '  ' + aelt
2025-07-02 06:41:17.355
2025-07-02 06:41:17.355         # pump out diffs from after the synch point
2025-07-02 06:41:17.355 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.355
2025-07-02 06:41:17.355 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.355 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.355
2025-07-02 06:41:17.355 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.355 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.355 alo = 215, ahi = 1101
2025-07-02 06:41:17.355 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.355 blo = 215, bhi = 1101
2025-07-02 06:41:17.355
2025-07-02 06:41:17.355     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.355         g = []
2025-07-02 06:41:17.355         if alo < ahi:
2025-07-02 06:41:17.355             if blo < bhi:
2025-07-02 06:41:17.356                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.356             else:
2025-07-02 06:41:17.356                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.356         elif blo < bhi:
2025-07-02 06:41:17.356             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.356
2025-07-02 06:41:17.356 >       yield from g
2025-07-02 06:41:17.356
2025-07-02 06:41:17.356 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.356 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.356
2025-07-02 06:41:17.356 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.356 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.356 alo = 215, ahi = 1101
2025-07-02 06:41:17.356 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.356 blo = 215, bhi = 1101
2025-07-02 06:41:17.356
2025-07-02 06:41:17.356     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.356         r"""
2025-07-02 06:41:17.356         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.357         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.357         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.357         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.357
2025-07-02 06:41:17.357         Example:
2025-07-02 06:41:17.357
2025-07-02 06:41:17.357         >>> d = Differ()
2025-07-02 06:41:17.357         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.357         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.357         >>> print(''.join(results), end="")
2025-07-02 06:41:17.357         - abcDefghiJkl
2025-07-02 06:41:17.357         + abcdefGhijkl
2025-07-02 06:41:17.357         """
2025-07-02 06:41:17.357
2025-07-02 06:41:17.357         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.357         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.357         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.357         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.358         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.358
2025-07-02 06:41:17.358         # search for the pair that matches best without being identical
2025-07-02 06:41:17.358         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.358         # on junk -- unless we have to)
2025-07-02 06:41:17.358         for j in range(blo, bhi):
2025-07-02 06:41:17.358             bj = b[j]
2025-07-02 06:41:17.358             cruncher.set_seq2(bj)
2025-07-02 06:41:17.358             for i in range(alo, ahi):
2025-07-02 06:41:17.358                 ai = a[i]
2025-07-02 06:41:17.358                 if ai == bj:
2025-07-02 06:41:17.358                     if eqi is None:
2025-07-02 06:41:17.358                         eqi, eqj = i, j
2025-07-02 06:41:17.358                     continue
2025-07-02 06:41:17.358                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.358                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.358                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.358                 # compares by a factor of 3.
2025-07-02 06:41:17.358                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.358                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.358                 # of the computation is cached by cruncher
2025-07-02 06:41:17.359                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.359                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.359                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.359                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.359         if best_ratio < cutoff:
2025-07-02 06:41:17.359             # no non-identical "pretty close" pair
2025-07-02 06:41:17.359             if eqi is None:
2025-07-02 06:41:17.359                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.359                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.359                 return
2025-07-02 06:41:17.359             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.359             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.359         else:
2025-07-02 06:41:17.359             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.359             eqi = None
2025-07-02 06:41:17.359
2025-07-02 06:41:17.359         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.359         # identical
2025-07-02 06:41:17.359
2025-07-02 06:41:17.359         # pump out diffs from before the synch point
2025-07-02 06:41:17.360         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.360
2025-07-02 06:41:17.360         # do intraline marking on the synch pair
2025-07-02 06:41:17.360         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.360         if eqi is None:
2025-07-02 06:41:17.360             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.360             atags = btags = ""
2025-07-02 06:41:17.360             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.360             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.360                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.360                 if tag == 'replace':
2025-07-02 06:41:17.360                     atags += '^' * la
2025-07-02 06:41:17.360                     btags += '^' * lb
2025-07-02 06:41:17.360                 elif tag == 'delete':
2025-07-02 06:41:17.360                     atags += '-' * la
2025-07-02 06:41:17.360                 elif tag == 'insert':
2025-07-02 06:41:17.360                     btags += '+' * lb
2025-07-02 06:41:17.360                 elif tag == 'equal':
2025-07-02 06:41:17.360                     atags += ' ' * la
2025-07-02 06:41:17.361                     btags += ' ' * lb
2025-07-02 06:41:17.361                 else:
2025-07-02 06:41:17.361                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.361             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.361         else:
2025-07-02 06:41:17.361             # the synch pair is identical
2025-07-02 06:41:17.361             yield '  ' + aelt
2025-07-02 06:41:17.361
2025-07-02 06:41:17.361         # pump out diffs from after the synch point
2025-07-02 06:41:17.361 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.361
2025-07-02 06:41:17.361 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.361 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.361
2025-07-02 06:41:17.361 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.361 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.361 alo = 216, ahi = 1101
2025-07-02 06:41:17.361 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.361 blo = 216, bhi = 1101
2025-07-02 06:41:17.362
2025-07-02 06:41:17.362     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.362         g = []
2025-07-02 06:41:17.362         if alo < ahi:
2025-07-02 06:41:17.362             if blo < bhi:
2025-07-02 06:41:17.362                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.362             else:
2025-07-02 06:41:17.362                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.362         elif blo < bhi:
2025-07-02 06:41:17.362             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.362
2025-07-02 06:41:17.362 >       yield from g
2025-07-02 06:41:17.362
2025-07-02 06:41:17.362 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.362 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.362
2025-07-02 06:41:17.362 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.362 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.362 alo = 216, ahi = 1101
2025-07-02 06:41:17.362 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.363 blo = 216, bhi = 1101
2025-07-02 06:41:17.363
2025-07-02 06:41:17.363     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.363         r"""
2025-07-02 06:41:17.363         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.363         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.363         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.363         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.363
2025-07-02 06:41:17.363         Example:
2025-07-02 06:41:17.363
2025-07-02 06:41:17.363         >>> d = Differ()
2025-07-02 06:41:17.363         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.363         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.363         >>> print(''.join(results), end="")
2025-07-02 06:41:17.363         - abcDefghiJkl
2025-07-02 06:41:17.364         + abcdefGhijkl
2025-07-02 06:41:17.364         """
2025-07-02 06:41:17.364
2025-07-02 06:41:17.364         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.364         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.364         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.364         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.364         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.364
2025-07-02 06:41:17.364         # search for the pair that matches best without being identical
2025-07-02 06:41:17.364         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.364         # on junk -- unless we have to)
2025-07-02 06:41:17.364         for j in range(blo, bhi):
2025-07-02 06:41:17.364             bj = b[j]
2025-07-02 06:41:17.364             cruncher.set_seq2(bj)
2025-07-02 06:41:17.364             for i in range(alo, ahi):
2025-07-02 06:41:17.364                 ai = a[i]
2025-07-02 06:41:17.364                 if ai == bj:
2025-07-02 06:41:17.364                     if eqi is None:
2025-07-02 06:41:17.365                         eqi, eqj = i, j
2025-07-02 06:41:17.365                     continue
2025-07-02 06:41:17.365                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.365                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.365                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.365                 # compares by a factor of 3.
2025-07-02 06:41:17.365                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.365                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.365                 # of the computation is cached by cruncher
2025-07-02 06:41:17.365                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.365                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.365                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.365                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.365         if best_ratio < cutoff:
2025-07-02 06:41:17.365             # no non-identical "pretty close" pair
2025-07-02 06:41:17.365             if eqi is None:
2025-07-02 06:41:17.365                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.365                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.365                 return
2025-07-02 06:41:17.366             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.366             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.366         else:
2025-07-02 06:41:17.366             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.366             eqi = None
2025-07-02 06:41:17.366
2025-07-02 06:41:17.366         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.366         # identical
2025-07-02 06:41:17.366
2025-07-02 06:41:17.366         # pump out diffs from before the synch point
2025-07-02 06:41:17.366         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.366
2025-07-02 06:41:17.366         # do intraline marking on the synch pair
2025-07-02 06:41:17.366         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.366         if eqi is None:
2025-07-02 06:41:17.366             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.366             atags = btags = ""
2025-07-02 06:41:17.366             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.366             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.366                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.367                 if tag == 'replace':
2025-07-02 06:41:17.367                     atags += '^' * la
2025-07-02 06:41:17.367                     btags += '^' * lb
2025-07-02 06:41:17.367                 elif tag == 'delete':
2025-07-02 06:41:17.367                     atags += '-' * la
2025-07-02 06:41:17.367                 elif tag == 'insert':
2025-07-02 06:41:17.367                     btags += '+' * lb
2025-07-02 06:41:17.367                 elif tag == 'equal':
2025-07-02 06:41:17.367                     atags += ' ' * la
2025-07-02 06:41:17.367                     btags += ' ' * lb
2025-07-02 06:41:17.367                 else:
2025-07-02 06:41:17.367                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.367             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.367         else:
2025-07-02 06:41:17.367             # the synch pair is identical
2025-07-02 06:41:17.367             yield '  ' + aelt
2025-07-02 06:41:17.367
2025-07-02 06:41:17.367         # pump out diffs from after the synch point
2025-07-02 06:41:17.367 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.367
2025-07-02 06:41:17.368 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.368 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.368
2025-07-02 06:41:17.368 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.368 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.368 alo = 217, ahi = 1101
2025-07-02 06:41:17.368 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.368 blo = 217, bhi = 1101
2025-07-02 06:41:17.368
2025-07-02 06:41:17.368     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.368         g = []
2025-07-02 06:41:17.368         if alo < ahi:
2025-07-02 06:41:17.368             if blo < bhi:
2025-07-02 06:41:17.368                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.368             else:
2025-07-02 06:41:17.368                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.368         elif blo < bhi:
2025-07-02 06:41:17.368             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.368
2025-07-02 06:41:17.369 >       yield from g
2025-07-02 06:41:17.369
2025-07-02 06:41:17.369 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.369 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.369
2025-07-02 06:41:17.369 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.369 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.369 alo = 217, ahi = 1101
2025-07-02 06:41:17.369 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.369 blo = 217, bhi = 1101
2025-07-02 06:41:17.369
2025-07-02 06:41:17.369     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.369         r"""
2025-07-02 06:41:17.369         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.369         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.369         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.369         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.369
2025-07-02 06:41:17.369         Example:
2025-07-02 06:41:17.370
2025-07-02 06:41:17.370         >>> d = Differ()
2025-07-02 06:41:17.370         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.370         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.370         >>> print(''.join(results), end="")
2025-07-02 06:41:17.370         - abcDefghiJkl
2025-07-02 06:41:17.370         + abcdefGhijkl
2025-07-02 06:41:17.370         """
2025-07-02 06:41:17.370
2025-07-02 06:41:17.370         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.370         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.370         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.370         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.370         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.370
2025-07-02 06:41:17.370         # search for the pair that matches best without being identical
2025-07-02 06:41:17.370         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.370         # on junk -- unless we have to)
2025-07-02 06:41:17.371         for j in range(blo, bhi):
2025-07-02 06:41:17.371             bj = b[j]
2025-07-02 06:41:17.371             cruncher.set_seq2(bj)
2025-07-02 06:41:17.371             for i in range(alo, ahi):
2025-07-02 06:41:17.371                 ai = a[i]
2025-07-02 06:41:17.371                 if ai == bj:
2025-07-02 06:41:17.371                     if eqi is None:
2025-07-02 06:41:17.371                         eqi, eqj = i, j
2025-07-02 06:41:17.371                     continue
2025-07-02 06:41:17.371                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.371                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.371                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.371                 # compares by a factor of 3.
2025-07-02 06:41:17.371                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.371                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.371                 # of the computation is cached by cruncher
2025-07-02 06:41:17.371                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.371                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.371                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.372                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.372         if best_ratio < cutoff:
2025-07-02 06:41:17.372             # no non-identical "pretty close" pair
2025-07-02 06:41:17.372             if eqi is None:
2025-07-02 06:41:17.372                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.372                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.372                 return
2025-07-02 06:41:17.372             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.372             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.372         else:
2025-07-02 06:41:17.372             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.372             eqi = None
2025-07-02 06:41:17.372
2025-07-02 06:41:17.372         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.372         # identical
2025-07-02 06:41:17.372
2025-07-02 06:41:17.372         # pump out diffs from before the synch point
2025-07-02 06:41:17.372         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.372
2025-07-02 06:41:17.372         # do intraline marking on the synch pair
2025-07-02 06:41:17.373         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.373         if eqi is None:
2025-07-02 06:41:17.373             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.373             atags = btags = ""
2025-07-02 06:41:17.373             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.373             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.373                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.373                 if tag == 'replace':
2025-07-02 06:41:17.373                     atags += '^' * la
2025-07-02 06:41:17.373                     btags += '^' * lb
2025-07-02 06:41:17.373                 elif tag == 'delete':
2025-07-02 06:41:17.373                     atags += '-' * la
2025-07-02 06:41:17.373                 elif tag == 'insert':
2025-07-02 06:41:17.373                     btags += '+' * lb
2025-07-02 06:41:17.373                 elif tag == 'equal':
2025-07-02 06:41:17.373                     atags += ' ' * la
2025-07-02 06:41:17.373                     btags += ' ' * lb
2025-07-02 06:41:17.373                 else:
2025-07-02 06:41:17.373                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.373             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.374         else:
2025-07-02 06:41:17.374             # the synch pair is identical
2025-07-02 06:41:17.374             yield '  ' + aelt
2025-07-02 06:41:17.374
2025-07-02 06:41:17.374         # pump out diffs from after the synch point
2025-07-02 06:41:17.374 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.374
2025-07-02 06:41:17.374 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.374 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.374
2025-07-02 06:41:17.374 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.374 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.374 alo = 218, ahi = 1101
2025-07-02 06:41:17.374 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.374 blo = 218, bhi = 1101
2025-07-02 06:41:17.374
2025-07-02 06:41:17.374     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.374         g = []
2025-07-02 06:41:17.374         if alo < ahi:
2025-07-02 06:41:17.374             if blo < bhi:
2025-07-02 06:41:17.375                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.375             else:
2025-07-02 06:41:17.375                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.375         elif blo < bhi:
2025-07-02 06:41:17.375             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.375
2025-07-02 06:41:17.375 >       yield from g
2025-07-02 06:41:17.375
2025-07-02 06:41:17.375 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.375 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.375
2025-07-02 06:41:17.375 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.375 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.375 alo = 218, ahi = 1101
2025-07-02 06:41:17.375 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.375 blo = 218, bhi = 1101
2025-07-02 06:41:17.375
2025-07-02 06:41:17.375     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.375         r"""
2025-07-02 06:41:17.376         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.376         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.376         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.376         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.376
2025-07-02 06:41:17.376         Example:
2025-07-02 06:41:17.376
2025-07-02 06:41:17.376         >>> d = Differ()
2025-07-02 06:41:17.376         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.376         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.376         >>> print(''.join(results), end="")
2025-07-02 06:41:17.376         - abcDefghiJkl
2025-07-02 06:41:17.376         + abcdefGhijkl
2025-07-02 06:41:17.376         """
2025-07-02 06:41:17.376
2025-07-02 06:41:17.376         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.376         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.376         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.377         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.377         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.377
2025-07-02 06:41:17.377         # search for the pair that matches best without being identical
2025-07-02 06:41:17.377         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.377         # on junk -- unless we have to)
2025-07-02 06:41:17.377         for j in range(blo, bhi):
2025-07-02 06:41:17.377             bj = b[j]
2025-07-02 06:41:17.377             cruncher.set_seq2(bj)
2025-07-02 06:41:17.377             for i in range(alo, ahi):
2025-07-02 06:41:17.377                 ai = a[i]
2025-07-02 06:41:17.377                 if ai == bj:
2025-07-02 06:41:17.377                     if eqi is None:
2025-07-02 06:41:17.377                         eqi, eqj = i, j
2025-07-02 06:41:17.377                     continue
2025-07-02 06:41:17.377                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.377                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.377                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.377                 # compares by a factor of 3.
2025-07-02 06:41:17.377                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.378                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.378                 # of the computation is cached by cruncher
2025-07-02 06:41:17.378                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.378                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.378                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.378                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.378         if best_ratio < cutoff:
2025-07-02 06:41:17.378             # no non-identical "pretty close" pair
2025-07-02 06:41:17.378             if eqi is None:
2025-07-02 06:41:17.378                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.378                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.378                 return
2025-07-02 06:41:17.378             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.378             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.378         else:
2025-07-02 06:41:17.378             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.378             eqi = None
2025-07-02 06:41:17.378
2025-07-02 06:41:17.378         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.379         # identical
2025-07-02 06:41:17.379
2025-07-02 06:41:17.379         # pump out diffs from before the synch point
2025-07-02 06:41:17.379         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.379
2025-07-02 06:41:17.379         # do intraline marking on the synch pair
2025-07-02 06:41:17.379         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.379         if eqi is None:
2025-07-02 06:41:17.379             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.379             atags = btags = ""
2025-07-02 06:41:17.379             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.379             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.379                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.379                 if tag == 'replace':
2025-07-02 06:41:17.379                     atags += '^' * la
2025-07-02 06:41:17.379                     btags += '^' * lb
2025-07-02 06:41:17.379                 elif tag == 'delete':
2025-07-02 06:41:17.379                     atags += '-' * la
2025-07-02 06:41:17.379                 elif tag == 'insert':
2025-07-02 06:41:17.380                     btags += '+' * lb
2025-07-02 06:41:17.380                 elif tag == 'equal':
2025-07-02 06:41:17.380                     atags += ' ' * la
2025-07-02 06:41:17.380                     btags += ' ' * lb
2025-07-02 06:41:17.380                 else:
2025-07-02 06:41:17.380                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.380             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.380         else:
2025-07-02 06:41:17.380             # the synch pair is identical
2025-07-02 06:41:17.380             yield '  ' + aelt
2025-07-02 06:41:17.380
2025-07-02 06:41:17.380         # pump out diffs from after the synch point
2025-07-02 06:41:17.380 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.380
2025-07-02 06:41:17.380 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.380 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.380
2025-07-02 06:41:17.380 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.380 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.381 alo = 219, ahi = 1101
2025-07-02 06:41:17.381 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.381 blo = 219, bhi = 1101
2025-07-02 06:41:17.381
2025-07-02 06:41:17.381     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.381         g = []
2025-07-02 06:41:17.381         if alo < ahi:
2025-07-02 06:41:17.381             if blo < bhi:
2025-07-02 06:41:17.381                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.381             else:
2025-07-02 06:41:17.381                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.381         elif blo < bhi:
2025-07-02 06:41:17.381             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.381
2025-07-02 06:41:17.381 >       yield from g
2025-07-02 06:41:17.381
2025-07-02 06:41:17.381 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.381 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.381
2025-07-02 06:41:17.381 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.382 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.382 alo = 219, ahi = 1101
2025-07-02 06:41:17.382 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.382 blo = 219, bhi = 1101
2025-07-02 06:41:17.382
2025-07-02 06:41:17.382     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.382         r"""
2025-07-02 06:41:17.382         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.382         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.382         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.382         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.382
2025-07-02 06:41:17.382         Example:
2025-07-02 06:41:17.382
2025-07-02 06:41:17.382         >>> d = Differ()
2025-07-02 06:41:17.382         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.382         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.382         >>> print(''.join(results), end="")
2025-07-02 06:41:17.382         - abcDefghiJkl
2025-07-02 06:41:17.383         + abcdefGhijkl
2025-07-02 06:41:17.383         """
2025-07-02 06:41:17.383
2025-07-02 06:41:17.383         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.383         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.383         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.383         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.383         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.383
2025-07-02 06:41:17.383         # search for the pair that matches best without being identical
2025-07-02 06:41:17.383         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.383         # on junk -- unless we have to)
2025-07-02 06:41:17.383         for j in range(blo, bhi):
2025-07-02 06:41:17.383             bj = b[j]
2025-07-02 06:41:17.383             cruncher.set_seq2(bj)
2025-07-02 06:41:17.383             for i in range(alo, ahi):
2025-07-02 06:41:17.383                 ai = a[i]
2025-07-02 06:41:17.383                 if ai == bj:
2025-07-02 06:41:17.383                     if eqi is None:
2025-07-02 06:41:17.384                         eqi, eqj = i, j
2025-07-02 06:41:17.384                     continue
2025-07-02 06:41:17.384                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.384                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.384                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.384                 # compares by a factor of 3.
2025-07-02 06:41:17.384                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.384                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.384                 # of the computation is cached by cruncher
2025-07-02 06:41:17.384                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.384                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.384                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.384                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.384         if best_ratio < cutoff:
2025-07-02 06:41:17.384             # no non-identical "pretty close" pair
2025-07-02 06:41:17.384             if eqi is None:
2025-07-02 06:41:17.384                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.384                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.384                 return
2025-07-02 06:41:17.384             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.385             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.385         else:
2025-07-02 06:41:17.385             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.385             eqi = None
2025-07-02 06:41:17.385
2025-07-02 06:41:17.385         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.385         # identical
2025-07-02 06:41:17.385
2025-07-02 06:41:17.385         # pump out diffs from before the synch point
2025-07-02 06:41:17.385         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.385
2025-07-02 06:41:17.385         # do intraline marking on the synch pair
2025-07-02 06:41:17.385         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.385         if eqi is None:
2025-07-02 06:41:17.385             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.385             atags = btags = ""
2025-07-02 06:41:17.385             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.385             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.385                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.386                 if tag == 'replace':
2025-07-02 06:41:17.386                     atags += '^' * la
2025-07-02 06:41:17.386                     btags += '^' * lb
2025-07-02 06:41:17.386                 elif tag == 'delete':
2025-07-02 06:41:17.386                     atags += '-' * la
2025-07-02 06:41:17.386                 elif tag == 'insert':
2025-07-02 06:41:17.386                     btags += '+' * lb
2025-07-02 06:41:17.386                 elif tag == 'equal':
2025-07-02 06:41:17.386                     atags += ' ' * la
2025-07-02 06:41:17.386                     btags += ' ' * lb
2025-07-02 06:41:17.386                 else:
2025-07-02 06:41:17.386                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.386             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.386         else:
2025-07-02 06:41:17.386             # the synch pair is identical
2025-07-02 06:41:17.386             yield '  ' + aelt
2025-07-02 06:41:17.386
2025-07-02 06:41:17.386         # pump out diffs from after the synch point
2025-07-02 06:41:17.386 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.386
2025-07-02 06:41:17.387 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.387 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.387
2025-07-02 06:41:17.387 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.387 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.387 alo = 220, ahi = 1101
2025-07-02 06:41:17.387 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.387 blo = 220, bhi = 1101
2025-07-02 06:41:17.387
2025-07-02 06:41:17.387     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.387         g = []
2025-07-02 06:41:17.387         if alo < ahi:
2025-07-02 06:41:17.387             if blo < bhi:
2025-07-02 06:41:17.387                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.387             else:
2025-07-02 06:41:17.387                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.387         elif blo < bhi:
2025-07-02 06:41:17.387             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.388
2025-07-02 06:41:17.388 >       yield from g
2025-07-02 06:41:17.388
2025-07-02 06:41:17.388 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.388 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.388
2025-07-02 06:41:17.388 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.388 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.388 alo = 220, ahi = 1101
2025-07-02 06:41:17.388 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.388 blo = 220, bhi = 1101
2025-07-02 06:41:17.388
2025-07-02 06:41:17.388     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.388         r"""
2025-07-02 06:41:17.388         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.388         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.388         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.388         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.389
2025-07-02 06:41:17.389         Example:
2025-07-02 06:41:17.389
2025-07-02 06:41:17.389         >>> d = Differ()
2025-07-02 06:41:17.389         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.389         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.389         >>> print(''.join(results), end="")
2025-07-02 06:41:17.389         - abcDefghiJkl
2025-07-02 06:41:17.389         + abcdefGhijkl
2025-07-02 06:41:17.389         """
2025-07-02 06:41:17.389
2025-07-02 06:41:17.389         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.389         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.389         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.389         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.389         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.389
2025-07-02 06:41:17.389         # search for the pair that matches best without being identical
2025-07-02 06:41:17.390         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.390         # on junk -- unless we have to)
2025-07-02 06:41:17.390         for j in range(blo, bhi):
2025-07-02 06:41:17.390             bj = b[j]
2025-07-02 06:41:17.390             cruncher.set_seq2(bj)
2025-07-02 06:41:17.390             for i in range(alo, ahi):
2025-07-02 06:41:17.390                 ai = a[i]
2025-07-02 06:41:17.390                 if ai == bj:
2025-07-02 06:41:17.390                     if eqi is None:
2025-07-02 06:41:17.390                         eqi, eqj = i, j
2025-07-02 06:41:17.390                     continue
2025-07-02 06:41:17.390                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.390                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.390                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.390                 # compares by a factor of 3.
2025-07-02 06:41:17.390                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.390                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.390                 # of the computation is cached by cruncher
2025-07-02 06:41:17.390                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.390                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.391                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.391                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.391         if best_ratio < cutoff:
2025-07-02 06:41:17.391             # no non-identical "pretty close" pair
2025-07-02 06:41:17.391             if eqi is None:
2025-07-02 06:41:17.391                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.391                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.391                 return
2025-07-02 06:41:17.391             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.391             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.391         else:
2025-07-02 06:41:17.391             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.391             eqi = None
2025-07-02 06:41:17.391
2025-07-02 06:41:17.391         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.391         # identical
2025-07-02 06:41:17.391
2025-07-02 06:41:17.391         # pump out diffs from before the synch point
2025-07-02 06:41:17.391         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.392
2025-07-02 06:41:17.392         # do intraline marking on the synch pair
2025-07-02 06:41:17.392         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.392         if eqi is None:
2025-07-02 06:41:17.392             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.392             atags = btags = ""
2025-07-02 06:41:17.392             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.392             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.392                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.392                 if tag == 'replace':
2025-07-02 06:41:17.392                     atags += '^' * la
2025-07-02 06:41:17.392                     btags += '^' * lb
2025-07-02 06:41:17.392                 elif tag == 'delete':
2025-07-02 06:41:17.392                     atags += '-' * la
2025-07-02 06:41:17.392                 elif tag == 'insert':
2025-07-02 06:41:17.392                     btags += '+' * lb
2025-07-02 06:41:17.392                 elif tag == 'equal':
2025-07-02 06:41:17.392                     atags += ' ' * la
2025-07-02 06:41:17.392                     btags += ' ' * lb
2025-07-02 06:41:17.392                 else:
2025-07-02 06:41:17.393                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.393             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.393         else:
2025-07-02 06:41:17.393             # the synch pair is identical
2025-07-02 06:41:17.393             yield '  ' + aelt
2025-07-02 06:41:17.393
2025-07-02 06:41:17.393         # pump out diffs from after the synch point
2025-07-02 06:41:17.393 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.393
2025-07-02 06:41:17.393 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.393 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.393
2025-07-02 06:41:17.393 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.393 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.393 alo = 221, ahi = 1101
2025-07-02 06:41:17.393 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.393 blo = 221, bhi = 1101
2025-07-02 06:41:17.393
2025-07-02 06:41:17.393     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.393         g = []
2025-07-02 06:41:17.394         if alo < ahi:
2025-07-02 06:41:17.394             if blo < bhi:
2025-07-02 06:41:17.394                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.394             else:
2025-07-02 06:41:17.394                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.394         elif blo < bhi:
2025-07-02 06:41:17.394             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.394
2025-07-02 06:41:17.394 >       yield from g
2025-07-02 06:41:17.394
2025-07-02 06:41:17.394 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.394 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.394
2025-07-02 06:41:17.394 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.394 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.394 alo = 221, ahi = 1101
2025-07-02 06:41:17.394 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.394 blo = 221, bhi = 1101
2025-07-02 06:41:17.394
2025-07-02 06:41:17.394     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.395         r"""
2025-07-02 06:41:17.395         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.395         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.395         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.395         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.395
2025-07-02 06:41:17.395         Example:
2025-07-02 06:41:17.395
2025-07-02 06:41:17.395         >>> d = Differ()
2025-07-02 06:41:17.395         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.395         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.395         >>> print(''.join(results), end="")
2025-07-02 06:41:17.395         - abcDefghiJkl
2025-07-02 06:41:17.395         + abcdefGhijkl
2025-07-02 06:41:17.395         """
2025-07-02 06:41:17.395
2025-07-02 06:41:17.396         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.396         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.396         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.396         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.396         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.396
2025-07-02 06:41:17.396         # search for the pair that matches best without being identical
2025-07-02 06:41:17.396         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.396         # on junk -- unless we have to)
2025-07-02 06:41:17.396         for j in range(blo, bhi):
2025-07-02 06:41:17.396             bj = b[j]
2025-07-02 06:41:17.396             cruncher.set_seq2(bj)
2025-07-02 06:41:17.396             for i in range(alo, ahi):
2025-07-02 06:41:17.396                 ai = a[i]
2025-07-02 06:41:17.396                 if ai == bj:
2025-07-02 06:41:17.396                     if eqi is None:
2025-07-02 06:41:17.396                         eqi, eqj = i, j
2025-07-02 06:41:17.396                     continue
2025-07-02 06:41:17.397                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.397                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.397                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.397                 # compares by a factor of 3.
2025-07-02 06:41:17.397                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.397                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.397                 # of the computation is cached by cruncher
2025-07-02 06:41:17.397                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.397                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.397                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.397                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.397         if best_ratio < cutoff:
2025-07-02 06:41:17.397             # no non-identical "pretty close" pair
2025-07-02 06:41:17.397             if eqi is None:
2025-07-02 06:41:17.397                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.397                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.397                 return
2025-07-02 06:41:17.397             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.397             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.398         else:
2025-07-02 06:41:17.398             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.398             eqi = None
2025-07-02 06:41:17.398
2025-07-02 06:41:17.398         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.398         # identical
2025-07-02 06:41:17.398
2025-07-02 06:41:17.398         # pump out diffs from before the synch point
2025-07-02 06:41:17.398         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.398
2025-07-02 06:41:17.398         # do intraline marking on the synch pair
2025-07-02 06:41:17.398         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.398         if eqi is None:
2025-07-02 06:41:17.398             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.398             atags = btags = ""
2025-07-02 06:41:17.398             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.398             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.398                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.398                 if tag == 'replace':
2025-07-02 06:41:17.398                     atags += '^' * la
2025-07-02 06:41:17.399                     btags += '^' * lb
2025-07-02 06:41:17.399                 elif tag == 'delete':
2025-07-02 06:41:17.399                     atags += '-' * la
2025-07-02 06:41:17.399                 elif tag == 'insert':
2025-07-02 06:41:17.399                     btags += '+' * lb
2025-07-02 06:41:17.399                 elif tag == 'equal':
2025-07-02 06:41:17.399                     atags += ' ' * la
2025-07-02 06:41:17.399                     btags += ' ' * lb
2025-07-02 06:41:17.399                 else:
2025-07-02 06:41:17.399                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.399             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.399         else:
2025-07-02 06:41:17.399             # the synch pair is identical
2025-07-02 06:41:17.399             yield '  ' + aelt
2025-07-02 06:41:17.399
2025-07-02 06:41:17.399         # pump out diffs from after the synch point
2025-07-02 06:41:17.399 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.399
2025-07-02 06:41:17.399 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.399 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.399
2025-07-02 06:41:17.400 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.400 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.400 alo = 224, ahi = 1101
2025-07-02 06:41:17.400 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.400 blo = 224, bhi = 1101
2025-07-02 06:41:17.400
2025-07-02 06:41:17.400     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.400         g = []
2025-07-02 06:41:17.400         if alo < ahi:
2025-07-02 06:41:17.400             if blo < bhi:
2025-07-02 06:41:17.400                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.400             else:
2025-07-02 06:41:17.400                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.400         elif blo < bhi:
2025-07-02 06:41:17.400             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.400
2025-07-02 06:41:17.400 >       yield from g
2025-07-02 06:41:17.400
2025-07-02 06:41:17.400 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.400 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.401
2025-07-02 06:41:17.401 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.401 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.401 alo = 224, ahi = 1101
2025-07-02 06:41:17.401 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.401 blo = 224, bhi = 1101
2025-07-02 06:41:17.401
2025-07-02 06:41:17.401     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.401         r"""
2025-07-02 06:41:17.401         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.401         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.401         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.401         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.401
2025-07-02 06:41:17.401         Example:
2025-07-02 06:41:17.401
2025-07-02 06:41:17.401         >>> d = Differ()
2025-07-02 06:41:17.401         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.401         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.401         >>> print(''.join(results), end="")
2025-07-02 06:41:17.402         - abcDefghiJkl
2025-07-02 06:41:17.402         + abcdefGhijkl
2025-07-02 06:41:17.402         """
2025-07-02 06:41:17.402
2025-07-02 06:41:17.402         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.402         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.402         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.402         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.402         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.402
2025-07-02 06:41:17.402         # search for the pair that matches best without being identical
2025-07-02 06:41:17.402         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.402         # on junk -- unless we have to)
2025-07-02 06:41:17.402         for j in range(blo, bhi):
2025-07-02 06:41:17.402             bj = b[j]
2025-07-02 06:41:17.402             cruncher.set_seq2(bj)
2025-07-02 06:41:17.402             for i in range(alo, ahi):
2025-07-02 06:41:17.402                 ai = a[i]
2025-07-02 06:41:17.402                 if ai == bj:
2025-07-02 06:41:17.403                     if eqi is None:
2025-07-02 06:41:17.403                         eqi, eqj = i, j
2025-07-02 06:41:17.403                     continue
2025-07-02 06:41:17.403                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.403                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.403                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.403                 # compares by a factor of 3.
2025-07-02 06:41:17.403                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.403                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.403                 # of the computation is cached by cruncher
2025-07-02 06:41:17.403                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.403                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.403                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.403                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.403         if best_ratio < cutoff:
2025-07-02 06:41:17.403             # no non-identical "pretty close" pair
2025-07-02 06:41:17.403             if eqi is None:
2025-07-02 06:41:17.403                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.403                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.403                 return
2025-07-02 06:41:17.404             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.404             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.404         else:
2025-07-02 06:41:17.404             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.404             eqi = None
2025-07-02 06:41:17.404
2025-07-02 06:41:17.404         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.404         # identical
2025-07-02 06:41:17.404
2025-07-02 06:41:17.404         # pump out diffs from before the synch point
2025-07-02 06:41:17.404         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.404
2025-07-02 06:41:17.404         # do intraline marking on the synch pair
2025-07-02 06:41:17.404         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.404         if eqi is None:
2025-07-02 06:41:17.404             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.404             atags = btags = ""
2025-07-02 06:41:17.404             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.404             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.404                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.405                 if tag == 'replace':
2025-07-02 06:41:17.405                     atags += '^' * la
2025-07-02 06:41:17.405                     btags += '^' * lb
2025-07-02 06:41:17.405                 elif tag == 'delete':
2025-07-02 06:41:17.405                     atags += '-' * la
2025-07-02 06:41:17.405                 elif tag == 'insert':
2025-07-02 06:41:17.405                     btags += '+' * lb
2025-07-02 06:41:17.405                 elif tag == 'equal':
2025-07-02 06:41:17.405                     atags += ' ' * la
2025-07-02 06:41:17.405                     btags += ' ' * lb
2025-07-02 06:41:17.405                 else:
2025-07-02 06:41:17.405                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.405             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.405         else:
2025-07-02 06:41:17.405             # the synch pair is identical
2025-07-02 06:41:17.405             yield '  ' + aelt
2025-07-02 06:41:17.405
2025-07-02 06:41:17.405         # pump out diffs from after the synch point
2025-07-02 06:41:17.405 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.405
2025-07-02 06:41:17.406 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.406 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.406
2025-07-02 06:41:17.406 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.406 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.406 alo = 225, ahi = 1101
2025-07-02 06:41:17.406 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.406 blo = 225, bhi = 1101
2025-07-02 06:41:17.406
2025-07-02 06:41:17.406     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.406         g = []
2025-07-02 06:41:17.406         if alo < ahi:
2025-07-02 06:41:17.406             if blo < bhi:
2025-07-02 06:41:17.406                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.406             else:
2025-07-02 06:41:17.406                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.406         elif blo < bhi:
2025-07-02 06:41:17.406             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.406
2025-07-02 06:41:17.407 >       yield from g
2025-07-02 06:41:17.407
2025-07-02 06:41:17.407 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.407 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.407
2025-07-02 06:41:17.407 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.407 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.407 alo = 225, ahi = 1101
2025-07-02 06:41:17.407 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.407 blo = 225, bhi = 1101
2025-07-02 06:41:17.407
2025-07-02 06:41:17.407     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.407         r"""
2025-07-02 06:41:17.407         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.407         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.407         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.407         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.407
2025-07-02 06:41:17.407         Example:
2025-07-02 06:41:17.407
2025-07-02 06:41:17.408         >>> d = Differ()
2025-07-02 06:41:17.408         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.408         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.408         >>> print(''.join(results), end="")
2025-07-02 06:41:17.408         - abcDefghiJkl
2025-07-02 06:41:17.408         + abcdefGhijkl
2025-07-02 06:41:17.408         """
2025-07-02 06:41:17.408
2025-07-02 06:41:17.408         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.408         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.408         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.408         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.408         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.408
2025-07-02 06:41:17.408         # search for the pair that matches best without being identical
2025-07-02 06:41:17.408         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.408         # on junk -- unless we have to)
2025-07-02 06:41:17.408         for j in range(blo, bhi):
2025-07-02 06:41:17.408             bj = b[j]
2025-07-02 06:41:17.409             cruncher.set_seq2(bj)
2025-07-02 06:41:17.409             for i in range(alo, ahi):
2025-07-02 06:41:17.409                 ai = a[i]
2025-07-02 06:41:17.409                 if ai == bj:
2025-07-02 06:41:17.409                     if eqi is None:
2025-07-02 06:41:17.409                         eqi, eqj = i, j
2025-07-02 06:41:17.409                     continue
2025-07-02 06:41:17.409                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.409                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.409                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.409                 # compares by a factor of 3.
2025-07-02 06:41:17.409                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.409                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.409                 # of the computation is cached by cruncher
2025-07-02 06:41:17.409                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.409                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.409                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.409                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.409         if best_ratio < cutoff:
2025-07-02 06:41:17.409             # no non-identical "pretty close" pair
2025-07-02 06:41:17.410             if eqi is None:
2025-07-02 06:41:17.410                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.410                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.410                 return
2025-07-02 06:41:17.410             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.410             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.410         else:
2025-07-02 06:41:17.410             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.410             eqi = None
2025-07-02 06:41:17.410
2025-07-02 06:41:17.410         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.410         # identical
2025-07-02 06:41:17.410
2025-07-02 06:41:17.410         # pump out diffs from before the synch point
2025-07-02 06:41:17.410         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.410
2025-07-02 06:41:17.410         # do intraline marking on the synch pair
2025-07-02 06:41:17.410         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.411         if eqi is None:
2025-07-02 06:41:17.411             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.411             atags = btags = ""
2025-07-02 06:41:17.411             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.411             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.411                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.411                 if tag == 'replace':
2025-07-02 06:41:17.411                     atags += '^' * la
2025-07-02 06:41:17.411                     btags += '^' * lb
2025-07-02 06:41:17.411                 elif tag == 'delete':
2025-07-02 06:41:17.411                     atags += '-' * la
2025-07-02 06:41:17.411                 elif tag == 'insert':
2025-07-02 06:41:17.411                     btags += '+' * lb
2025-07-02 06:41:17.411                 elif tag == 'equal':
2025-07-02 06:41:17.411                     atags += ' ' * la
2025-07-02 06:41:17.411                     btags += ' ' * lb
2025-07-02 06:41:17.411                 else:
2025-07-02 06:41:17.411                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.411             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.411         else:
2025-07-02 06:41:17.412             # the synch pair is identical
2025-07-02 06:41:17.412             yield '  ' + aelt
2025-07-02 06:41:17.412
2025-07-02 06:41:17.412         # pump out diffs from after the synch point
2025-07-02 06:41:17.412 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.412
2025-07-02 06:41:17.412 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.412 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.412
2025-07-02 06:41:17.412 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.412 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.412 alo = 226, ahi = 1101
2025-07-02 06:41:17.412 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.412 blo = 226, bhi = 1101
2025-07-02 06:41:17.412
2025-07-02 06:41:17.412     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.412         g = []
2025-07-02 06:41:17.412         if alo < ahi:
2025-07-02 06:41:17.412             if blo < bhi:
2025-07-02 06:41:17.412                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.413             else:
2025-07-02 06:41:17.413                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.413         elif blo < bhi:
2025-07-02 06:41:17.413             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.413
2025-07-02 06:41:17.413 >       yield from g
2025-07-02 06:41:17.413
2025-07-02 06:41:17.413 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.413 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.413
2025-07-02 06:41:17.413 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.413 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.413 alo = 226, ahi = 1101
2025-07-02 06:41:17.413 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.413 blo = 226, bhi = 1101
2025-07-02 06:41:17.413
2025-07-02 06:41:17.413     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.413         r"""
2025-07-02 06:41:17.414         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.414         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.414         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.414         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.414
2025-07-02 06:41:17.414         Example:
2025-07-02 06:41:17.414
2025-07-02 06:41:17.414         >>> d = Differ()
2025-07-02 06:41:17.414         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.414         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.414         >>> print(''.join(results), end="")
2025-07-02 06:41:17.414         - abcDefghiJkl
2025-07-02 06:41:17.414         + abcdefGhijkl
2025-07-02 06:41:17.414         """
2025-07-02 06:41:17.414
2025-07-02 06:41:17.414         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.414         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.415         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.415         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.415         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.415
2025-07-02 06:41:17.415         # search for the pair that matches best without being identical
2025-07-02 06:41:17.415         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.415         # on junk -- unless we have to)
2025-07-02 06:41:17.415         for j in range(blo, bhi):
2025-07-02 06:41:17.415             bj = b[j]
2025-07-02 06:41:17.415             cruncher.set_seq2(bj)
2025-07-02 06:41:17.415             for i in range(alo, ahi):
2025-07-02 06:41:17.415                 ai = a[i]
2025-07-02 06:41:17.415                 if ai == bj:
2025-07-02 06:41:17.415                     if eqi is None:
2025-07-02 06:41:17.415                         eqi, eqj = i, j
2025-07-02 06:41:17.415                     continue
2025-07-02 06:41:17.415                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.415                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.415                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.415                 # compares by a factor of 3.
2025-07-02 06:41:17.416                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.416                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.416                 # of the computation is cached by cruncher
2025-07-02 06:41:17.416                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.416                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.416                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.416                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.416         if best_ratio < cutoff:
2025-07-02 06:41:17.416             # no non-identical "pretty close" pair
2025-07-02 06:41:17.416             if eqi is None:
2025-07-02 06:41:17.416                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.416                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.416                 return
2025-07-02 06:41:17.416             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.416             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.416         else:
2025-07-02 06:41:17.416             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.416             eqi = None
2025-07-02 06:41:17.416
2025-07-02 06:41:17.416         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.417         # identical
2025-07-02 06:41:17.417
2025-07-02 06:41:17.417         # pump out diffs from before the synch point
2025-07-02 06:41:17.417         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.417
2025-07-02 06:41:17.417         # do intraline marking on the synch pair
2025-07-02 06:41:17.417         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.417         if eqi is None:
2025-07-02 06:41:17.417             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.417             atags = btags = ""
2025-07-02 06:41:17.417             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.417             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.417                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.417                 if tag == 'replace':
2025-07-02 06:41:17.417                     atags += '^' * la
2025-07-02 06:41:17.417                     btags += '^' * lb
2025-07-02 06:41:17.417                 elif tag == 'delete':
2025-07-02 06:41:17.417                     atags += '-' * la
2025-07-02 06:41:17.417                 elif tag == 'insert':
2025-07-02 06:41:17.417                     btags += '+' * lb
2025-07-02 06:41:17.418                 elif tag == 'equal':
2025-07-02 06:41:17.418                     atags += ' ' * la
2025-07-02 06:41:17.418                     btags += ' ' * lb
2025-07-02 06:41:17.418                 else:
2025-07-02 06:41:17.418                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.418             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.418         else:
2025-07-02 06:41:17.418             # the synch pair is identical
2025-07-02 06:41:17.418             yield '  ' + aelt
2025-07-02 06:41:17.418
2025-07-02 06:41:17.418         # pump out diffs from after the synch point
2025-07-02 06:41:17.418 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.418
2025-07-02 06:41:17.418 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.418 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.418
2025-07-02 06:41:17.418 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.418 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.418 alo = 227, ahi = 1101
2025-07-02 06:41:17.418 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.419 blo = 227, bhi = 1101
2025-07-02 06:41:17.419
2025-07-02 06:41:17.419     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.419         g = []
2025-07-02 06:41:17.419         if alo < ahi:
2025-07-02 06:41:17.419             if blo < bhi:
2025-07-02 06:41:17.419                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.419             else:
2025-07-02 06:41:17.419                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.419         elif blo < bhi:
2025-07-02 06:41:17.419             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.419
2025-07-02 06:41:17.419 >       yield from g
2025-07-02 06:41:17.419
2025-07-02 06:41:17.419 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.419 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.419
2025-07-02 06:41:17.419 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.419 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.419 alo = 227, ahi = 1101
2025-07-02 06:41:17.419 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.420 blo = 227, bhi = 1101
2025-07-02 06:41:17.420
2025-07-02 06:41:17.420     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.420         r"""
2025-07-02 06:41:17.420         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.420         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.420         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.420         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.420
2025-07-02 06:41:17.420         Example:
2025-07-02 06:41:17.420
2025-07-02 06:41:17.420         >>> d = Differ()
2025-07-02 06:41:17.420         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.420         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.420         >>> print(''.join(results), end="")
2025-07-02 06:41:17.420         - abcDefghiJkl
2025-07-02 06:41:17.420         + abcdefGhijkl
2025-07-02 06:41:17.420         """
2025-07-02 06:41:17.421
2025-07-02 06:41:17.421         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.421         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.421         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.421         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.421         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.421
2025-07-02 06:41:17.421         # search for the pair that matches best without being identical
2025-07-02 06:41:17.421         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.421         # on junk -- unless we have to)
2025-07-02 06:41:17.421         for j in range(blo, bhi):
2025-07-02 06:41:17.421             bj = b[j]
2025-07-02 06:41:17.421             cruncher.set_seq2(bj)
2025-07-02 06:41:17.421             for i in range(alo, ahi):
2025-07-02 06:41:17.421                 ai = a[i]
2025-07-02 06:41:17.421                 if ai == bj:
2025-07-02 06:41:17.421                     if eqi is None:
2025-07-02 06:41:17.421                         eqi, eqj = i, j
2025-07-02 06:41:17.421                     continue
2025-07-02 06:41:17.421                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.422                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.422                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.422                 # compares by a factor of 3.
2025-07-02 06:41:17.422                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.422                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.422                 # of the computation is cached by cruncher
2025-07-02 06:41:17.422                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.422                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.422                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.422                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.422         if best_ratio < cutoff:
2025-07-02 06:41:17.422             # no non-identical "pretty close" pair
2025-07-02 06:41:17.422             if eqi is None:
2025-07-02 06:41:17.422                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.422                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.422                 return
2025-07-02 06:41:17.422             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.422             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.423         else:
2025-07-02 06:41:17.423             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.423             eqi = None
2025-07-02 06:41:17.423
2025-07-02 06:41:17.423         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.423         # identical
2025-07-02 06:41:17.423
2025-07-02 06:41:17.423         # pump out diffs from before the synch point
2025-07-02 06:41:17.423         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.423
2025-07-02 06:41:17.423         # do intraline marking on the synch pair
2025-07-02 06:41:17.423         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.423         if eqi is None:
2025-07-02 06:41:17.423             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.423             atags = btags = ""
2025-07-02 06:41:17.423             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.423             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.423                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.423                 if tag == 'replace':
2025-07-02 06:41:17.424                     atags += '^' * la
2025-07-02 06:41:17.424                     btags += '^' * lb
2025-07-02 06:41:17.424                 elif tag == 'delete':
2025-07-02 06:41:17.424                     atags += '-' * la
2025-07-02 06:41:17.424                 elif tag == 'insert':
2025-07-02 06:41:17.424                     btags += '+' * lb
2025-07-02 06:41:17.424                 elif tag == 'equal':
2025-07-02 06:41:17.424                     atags += ' ' * la
2025-07-02 06:41:17.424                     btags += ' ' * lb
2025-07-02 06:41:17.424                 else:
2025-07-02 06:41:17.424                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.424             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.424         else:
2025-07-02 06:41:17.424             # the synch pair is identical
2025-07-02 06:41:17.424             yield '  ' + aelt
2025-07-02 06:41:17.424
2025-07-02 06:41:17.424         # pump out diffs from after the synch point
2025-07-02 06:41:17.424 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.424
2025-07-02 06:41:17.424 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.425 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.425
2025-07-02 06:41:17.425 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.425 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.425 alo = 228, ahi = 1101
2025-07-02 06:41:17.425 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.425 blo = 228, bhi = 1101
2025-07-02 06:41:17.425
2025-07-02 06:41:17.425     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.425         g = []
2025-07-02 06:41:17.425         if alo < ahi:
2025-07-02 06:41:17.425             if blo < bhi:
2025-07-02 06:41:17.425                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.425             else:
2025-07-02 06:41:17.425                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.425         elif blo < bhi:
2025-07-02 06:41:17.425             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.425
2025-07-02 06:41:17.425 >       yield from g
2025-07-02 06:41:17.425
2025-07-02 06:41:17.426 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.426 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.426
2025-07-02 06:41:17.426 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.426 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.426 alo = 228, ahi = 1101
2025-07-02 06:41:17.426 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.426 blo = 228, bhi = 1101
2025-07-02 06:41:17.426
2025-07-02 06:41:17.426     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.426         r"""
2025-07-02 06:41:17.426         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.426         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.426         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.426         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.426
2025-07-02 06:41:17.426         Example:
2025-07-02 06:41:17.426
2025-07-02 06:41:17.427         >>> d = Differ()
2025-07-02 06:41:17.427         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.427         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.427         >>> print(''.join(results), end="")
2025-07-02 06:41:17.427         - abcDefghiJkl
2025-07-02 06:41:17.427         + abcdefGhijkl
2025-07-02 06:41:17.427         """
2025-07-02 06:41:17.427
2025-07-02 06:41:17.427         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.427         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.427         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.427         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.427         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.427
2025-07-02 06:41:17.427         # search for the pair that matches best without being identical
2025-07-02 06:41:17.427         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.427         # on junk -- unless we have to)
2025-07-02 06:41:17.427         for j in range(blo, bhi):
2025-07-02 06:41:17.428             bj = b[j]
2025-07-02 06:41:17.428             cruncher.set_seq2(bj)
2025-07-02 06:41:17.428             for i in range(alo, ahi):
2025-07-02 06:41:17.428                 ai = a[i]
2025-07-02 06:41:17.428                 if ai == bj:
2025-07-02 06:41:17.428                     if eqi is None:
2025-07-02 06:41:17.428                         eqi, eqj = i, j
2025-07-02 06:41:17.428                     continue
2025-07-02 06:41:17.428                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.428                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.428                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.428                 # compares by a factor of 3.
2025-07-02 06:41:17.428                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.428                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.428                 # of the computation is cached by cruncher
2025-07-02 06:41:17.428                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.428                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.428                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.428                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.428         if best_ratio < cutoff:
2025-07-02 06:41:17.429             # no non-identical "pretty close" pair
2025-07-02 06:41:17.429             if eqi is None:
2025-07-02 06:41:17.429                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.429                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.429                 return
2025-07-02 06:41:17.429             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.429             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.429         else:
2025-07-02 06:41:17.429             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.429             eqi = None
2025-07-02 06:41:17.429
2025-07-02 06:41:17.429         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.429         # identical
2025-07-02 06:41:17.429
2025-07-02 06:41:17.429         # pump out diffs from before the synch point
2025-07-02 06:41:17.429         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.429
2025-07-02 06:41:17.429         # do intraline marking on the synch pair
2025-07-02 06:41:17.429         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.429         if eqi is None:
2025-07-02 06:41:17.430             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.430             atags = btags = ""
2025-07-02 06:41:17.430             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.430             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.430                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.430                 if tag == 'replace':
2025-07-02 06:41:17.430                     atags += '^' * la
2025-07-02 06:41:17.430                     btags += '^' * lb
2025-07-02 06:41:17.430                 elif tag == 'delete':
2025-07-02 06:41:17.430                     atags += '-' * la
2025-07-02 06:41:17.430                 elif tag == 'insert':
2025-07-02 06:41:17.430                     btags += '+' * lb
2025-07-02 06:41:17.430                 elif tag == 'equal':
2025-07-02 06:41:17.430                     atags += ' ' * la
2025-07-02 06:41:17.430                     btags += ' ' * lb
2025-07-02 06:41:17.430                 else:
2025-07-02 06:41:17.430                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.430             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.430         else:
2025-07-02 06:41:17.431             # the synch pair is identical
2025-07-02 06:41:17.431             yield '  ' + aelt
2025-07-02 06:41:17.431
2025-07-02 06:41:17.431         # pump out diffs from after the synch point
2025-07-02 06:41:17.431 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.431
2025-07-02 06:41:17.431 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.431 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.431
2025-07-02 06:41:17.431 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.431 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.431 alo = 229, ahi = 1101
2025-07-02 06:41:17.431 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.431 blo = 229, bhi = 1101
2025-07-02 06:41:17.431
2025-07-02 06:41:17.431     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.431         g = []
2025-07-02 06:41:17.432         if alo < ahi:
2025-07-02 06:41:17.432             if blo < bhi:
2025-07-02 06:41:17.432                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.432             else:
2025-07-02 06:41:17.432                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.432         elif blo < bhi:
2025-07-02 06:41:17.432             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.432
2025-07-02 06:41:17.432 >       yield from g
2025-07-02 06:41:17.432
2025-07-02 06:41:17.432 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.432 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.432
2025-07-02 06:41:17.432 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.432 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.432 alo = 229, ahi = 1101
2025-07-02 06:41:17.432 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.432 blo = 229, bhi = 1101
2025-07-02 06:41:17.432
2025-07-02 06:41:17.433     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.433         r"""
2025-07-02 06:41:17.433         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.433         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.433         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.433         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.433
2025-07-02 06:41:17.433         Example:
2025-07-02 06:41:17.433
2025-07-02 06:41:17.433         >>> d = Differ()
2025-07-02 06:41:17.433         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.433         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.433         >>> print(''.join(results), end="")
2025-07-02 06:41:17.433         - abcDefghiJkl
2025-07-02 06:41:17.433         + abcdefGhijkl
2025-07-02 06:41:17.433         """
2025-07-02 06:41:17.433
2025-07-02 06:41:17.433         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.434         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.434         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.434         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.434         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.434
2025-07-02 06:41:17.434         # search for the pair that matches best without being identical
2025-07-02 06:41:17.434         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.434         # on junk -- unless we have to)
2025-07-02 06:41:17.434         for j in range(blo, bhi):
2025-07-02 06:41:17.434             bj = b[j]
2025-07-02 06:41:17.434             cruncher.set_seq2(bj)
2025-07-02 06:41:17.434             for i in range(alo, ahi):
2025-07-02 06:41:17.434                 ai = a[i]
2025-07-02 06:41:17.434                 if ai == bj:
2025-07-02 06:41:17.434                     if eqi is None:
2025-07-02 06:41:17.434                         eqi, eqj = i, j
2025-07-02 06:41:17.434                     continue
2025-07-02 06:41:17.434                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.434                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.434                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.435                 # compares by a factor of 3.
2025-07-02 06:41:17.435                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.435                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.435                 # of the computation is cached by cruncher
2025-07-02 06:41:17.435                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.435                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.435                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.435                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.435         if best_ratio < cutoff:
2025-07-02 06:41:17.435             # no non-identical "pretty close" pair
2025-07-02 06:41:17.435             if eqi is None:
2025-07-02 06:41:17.435                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.435                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.435                 return
2025-07-02 06:41:17.435             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.435             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.435         else:
2025-07-02 06:41:17.436             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.436             eqi = None
2025-07-02 06:41:17.436
2025-07-02 06:41:17.436         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.436         # identical
2025-07-02 06:41:17.436
2025-07-02 06:41:17.436         # pump out diffs from before the synch point
2025-07-02 06:41:17.436         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.436
2025-07-02 06:41:17.436         # do intraline marking on the synch pair
2025-07-02 06:41:17.436         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.436         if eqi is None:
2025-07-02 06:41:17.436             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.436             atags = btags = ""
2025-07-02 06:41:17.436             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.436             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.436                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.436                 if tag == 'replace':
2025-07-02 06:41:17.436                     atags += '^' * la
2025-07-02 06:41:17.437                     btags += '^' * lb
2025-07-02 06:41:17.437                 elif tag == 'delete':
2025-07-02 06:41:17.437                     atags += '-' * la
2025-07-02 06:41:17.437                 elif tag == 'insert':
2025-07-02 06:41:17.437                     btags += '+' * lb
2025-07-02 06:41:17.437                 elif tag == 'equal':
2025-07-02 06:41:17.437                     atags += ' ' * la
2025-07-02 06:41:17.437                     btags += ' ' * lb
2025-07-02 06:41:17.437                 else:
2025-07-02 06:41:17.437                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.437             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.437         else:
2025-07-02 06:41:17.437             # the synch pair is identical
2025-07-02 06:41:17.437             yield '  ' + aelt
2025-07-02 06:41:17.437
2025-07-02 06:41:17.437         # pump out diffs from after the synch point
2025-07-02 06:41:17.437 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.437
2025-07-02 06:41:17.437 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.438 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.438
2025-07-02 06:41:17.438 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.438 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.438 alo = 230, ahi = 1101
2025-07-02 06:41:17.438 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.438 blo = 230, bhi = 1101
2025-07-02 06:41:17.438
2025-07-02 06:41:17.438     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.438         g = []
2025-07-02 06:41:17.438         if alo < ahi:
2025-07-02 06:41:17.438             if blo < bhi:
2025-07-02 06:41:17.438                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.438             else:
2025-07-02 06:41:17.438                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.438         elif blo < bhi:
2025-07-02 06:41:17.438             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.438
2025-07-02 06:41:17.438 >       yield from g
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.439 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.439 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.439 alo = 230, ahi = 1101
2025-07-02 06:41:17.439 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.439 blo = 230, bhi = 1101
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.439         r"""
2025-07-02 06:41:17.439         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.439         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.439         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.439         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439         Example:
2025-07-02 06:41:17.439
2025-07-02 06:41:17.439         >>> d = Differ()
2025-07-02 06:41:17.440         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.440         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.440         >>> print(''.join(results), end="")
2025-07-02 06:41:17.440         - abcDefghiJkl
2025-07-02 06:41:17.440         + abcdefGhijkl
2025-07-02 06:41:17.440         """
2025-07-02 06:41:17.440
2025-07-02 06:41:17.440         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.440         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.440         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.440         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.440         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.440
2025-07-02 06:41:17.440         # search for the pair that matches best without being identical
2025-07-02 06:41:17.440         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.440         # on junk -- unless we have to)
2025-07-02 06:41:17.441         for j in range(blo, bhi):
2025-07-02 06:41:17.441             bj = b[j]
2025-07-02 06:41:17.441             cruncher.set_seq2(bj)
2025-07-02 06:41:17.441             for i in range(alo, ahi):
2025-07-02 06:41:17.441                 ai = a[i]
2025-07-02 06:41:17.441                 if ai == bj:
2025-07-02 06:41:17.441                     if eqi is None:
2025-07-02 06:41:17.441                         eqi, eqj = i, j
2025-07-02 06:41:17.441                     continue
2025-07-02 06:41:17.441                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.441                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.441                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.441                 # compares by a factor of 3.
2025-07-02 06:41:17.441                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.441                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.441                 # of the computation is cached by cruncher
2025-07-02 06:41:17.441                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.442                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.442                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.442                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.442         if best_ratio < cutoff:
2025-07-02 06:41:17.442             # no non-identical "pretty close" pair
2025-07-02 06:41:17.442             if eqi is None:
2025-07-02 06:41:17.442                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.442                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.442                 return
2025-07-02 06:41:17.442             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.442             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.442         else:
2025-07-02 06:41:17.442             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.442             eqi = None
2025-07-02 06:41:17.442
2025-07-02 06:41:17.442         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.442         # identical
2025-07-02 06:41:17.442
2025-07-02 06:41:17.442         # pump out diffs from before the synch point
2025-07-02 06:41:17.443         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.443
2025-07-02 06:41:17.443         # do intraline marking on the synch pair
2025-07-02 06:41:17.443         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.443         if eqi is None:
2025-07-02 06:41:17.443             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.443             atags = btags = ""
2025-07-02 06:41:17.443             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.443             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.443                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.443                 if tag == 'replace':
2025-07-02 06:41:17.443                     atags += '^' * la
2025-07-02 06:41:17.443                     btags += '^' * lb
2025-07-02 06:41:17.443                 elif tag == 'delete':
2025-07-02 06:41:17.443                     atags += '-' * la
2025-07-02 06:41:17.443                 elif tag == 'insert':
2025-07-02 06:41:17.443                     btags += '+' * lb
2025-07-02 06:41:17.444                 elif tag == 'equal':
2025-07-02 06:41:17.444                     atags += ' ' * la
2025-07-02 06:41:17.444                     btags += ' ' * lb
2025-07-02 06:41:17.444                 else:
2025-07-02 06:41:17.444                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.444             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.444         else:
2025-07-02 06:41:17.444             # the synch pair is identical
2025-07-02 06:41:17.444             yield '  ' + aelt
2025-07-02 06:41:17.444
2025-07-02 06:41:17.444         # pump out diffs from after the synch point
2025-07-02 06:41:17.444 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.444
2025-07-02 06:41:17.444 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.444 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.444
2025-07-02 06:41:17.444 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.444 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.444 alo = 231, ahi = 1101
2025-07-02 06:41:17.445 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.445 blo = 231, bhi = 1101
2025-07-02 06:41:17.445
2025-07-02 06:41:17.445     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.445         g = []
2025-07-02 06:41:17.445         if alo < ahi:
2025-07-02 06:41:17.445             if blo < bhi:
2025-07-02 06:41:17.445                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.445             else:
2025-07-02 06:41:17.445                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.445         elif blo < bhi:
2025-07-02 06:41:17.445             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.445
2025-07-02 06:41:17.445 >       yield from g
2025-07-02 06:41:17.445
2025-07-02 06:41:17.445 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.445 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.445
2025-07-02 06:41:17.445 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.445 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.446 alo = 231, ahi = 1101
2025-07-02 06:41:17.446 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.446 blo = 231, bhi = 1101
2025-07-02 06:41:17.446
2025-07-02 06:41:17.446     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.446         r"""
2025-07-02 06:41:17.446         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.446         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.446         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.446         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.446
2025-07-02 06:41:17.446         Example:
2025-07-02 06:41:17.446
2025-07-02 06:41:17.446         >>> d = Differ()
2025-07-02 06:41:17.446         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.446         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.446         >>> print(''.join(results), end="")
2025-07-02 06:41:17.446         - abcDefghiJkl
2025-07-02 06:41:17.447         + abcdefGhijkl
2025-07-02 06:41:17.447         """
2025-07-02 06:41:17.447
2025-07-02 06:41:17.447         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.447         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.447         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.447         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.447         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.447
2025-07-02 06:41:17.447         # search for the pair that matches best without being identical
2025-07-02 06:41:17.447         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.447         # on junk -- unless we have to)
2025-07-02 06:41:17.447         for j in range(blo, bhi):
2025-07-02 06:41:17.447             bj = b[j]
2025-07-02 06:41:17.447             cruncher.set_seq2(bj)
2025-07-02 06:41:17.447             for i in range(alo, ahi):
2025-07-02 06:41:17.447                 ai = a[i]
2025-07-02 06:41:17.447                 if ai == bj:
2025-07-02 06:41:17.447                     if eqi is None:
2025-07-02 06:41:17.448                         eqi, eqj = i, j
2025-07-02 06:41:17.448                     continue
2025-07-02 06:41:17.448                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.448                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.448                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.448                 # compares by a factor of 3.
2025-07-02 06:41:17.448                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.448                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.448                 # of the computation is cached by cruncher
2025-07-02 06:41:17.448                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.448                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.448                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.448                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.448         if best_ratio < cutoff:
2025-07-02 06:41:17.448             # no non-identical "pretty close" pair
2025-07-02 06:41:17.448             if eqi is None:
2025-07-02 06:41:17.448                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.448                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.448                 return
2025-07-02 06:41:17.448             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.449             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.449         else:
2025-07-02 06:41:17.449             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.449             eqi = None
2025-07-02 06:41:17.449
2025-07-02 06:41:17.449         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.449         # identical
2025-07-02 06:41:17.449
2025-07-02 06:41:17.449         # pump out diffs from before the synch point
2025-07-02 06:41:17.449         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.449
2025-07-02 06:41:17.449         # do intraline marking on the synch pair
2025-07-02 06:41:17.449         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.449         if eqi is None:
2025-07-02 06:41:17.449             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.449             atags = btags = ""
2025-07-02 06:41:17.449             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.450             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.450                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.450                 if tag == 'replace':
2025-07-02 06:41:17.450                     atags += '^' * la
2025-07-02 06:41:17.450                     btags += '^' * lb
2025-07-02 06:41:17.450                 elif tag == 'delete':
2025-07-02 06:41:17.450                     atags += '-' * la
2025-07-02 06:41:17.450                 elif tag == 'insert':
2025-07-02 06:41:17.450                     btags += '+' * lb
2025-07-02 06:41:17.450                 elif tag == 'equal':
2025-07-02 06:41:17.450                     atags += ' ' * la
2025-07-02 06:41:17.450                     btags += ' ' * lb
2025-07-02 06:41:17.450                 else:
2025-07-02 06:41:17.450                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.450             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.450         else:
2025-07-02 06:41:17.450             # the synch pair is identical
2025-07-02 06:41:17.450             yield '  ' + aelt
2025-07-02 06:41:17.450
2025-07-02 06:41:17.451         # pump out diffs from after the synch point
2025-07-02 06:41:17.451 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.451
2025-07-02 06:41:17.451 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.451 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.451
2025-07-02 06:41:17.451 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.451 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.451 alo = 232, ahi = 1101
2025-07-02 06:41:17.451 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.451 blo = 232, bhi = 1101
2025-07-02 06:41:17.451
2025-07-02 06:41:17.451     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.451         g = []
2025-07-02 06:41:17.451         if alo < ahi:
2025-07-02 06:41:17.451             if blo < bhi:
2025-07-02 06:41:17.451                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.451             else:
2025-07-02 06:41:17.451                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.452         elif blo < bhi:
2025-07-02 06:41:17.452             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.452
2025-07-02 06:41:17.452 >       yield from g
2025-07-02 06:41:17.452
2025-07-02 06:41:17.452 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.452 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.452
2025-07-02 06:41:17.452 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.452 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.452 alo = 232, ahi = 1101
2025-07-02 06:41:17.452 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.452 blo = 232, bhi = 1101
2025-07-02 06:41:17.452
2025-07-02 06:41:17.452     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.452         r"""
2025-07-02 06:41:17.452         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.452         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.452         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.453         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.453
2025-07-02 06:41:17.453         Example:
2025-07-02 06:41:17.453
2025-07-02 06:41:17.453         >>> d = Differ()
2025-07-02 06:41:17.453         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.453         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.453         >>> print(''.join(results), end="")
2025-07-02 06:41:17.453         - abcDefghiJkl
2025-07-02 06:41:17.453         + abcdefGhijkl
2025-07-02 06:41:17.453         """
2025-07-02 06:41:17.453
2025-07-02 06:41:17.453         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.453         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.453         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.453         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.453         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.453
2025-07-02 06:41:17.454         # search for the pair that matches best without being identical
2025-07-02 06:41:17.454         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.454         # on junk -- unless we have to)
2025-07-02 06:41:17.454         for j in range(blo, bhi):
2025-07-02 06:41:17.454             bj = b[j]
2025-07-02 06:41:17.454             cruncher.set_seq2(bj)
2025-07-02 06:41:17.454             for i in range(alo, ahi):
2025-07-02 06:41:17.454                 ai = a[i]
2025-07-02 06:41:17.454                 if ai == bj:
2025-07-02 06:41:17.454                     if eqi is None:
2025-07-02 06:41:17.454                         eqi, eqj = i, j
2025-07-02 06:41:17.454                     continue
2025-07-02 06:41:17.454                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.454                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.454                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.454                 # compares by a factor of 3.
2025-07-02 06:41:17.454                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.454                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.454                 # of the computation is cached by cruncher
2025-07-02 06:41:17.455                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.455                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.455                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.455                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.455         if best_ratio < cutoff:
2025-07-02 06:41:17.455             # no non-identical "pretty close" pair
2025-07-02 06:41:17.455             if eqi is None:
2025-07-02 06:41:17.455                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.455                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.455                 return
2025-07-02 06:41:17.455             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.455             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.455         else:
2025-07-02 06:41:17.455             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.455             eqi = None
2025-07-02 06:41:17.455
2025-07-02 06:41:17.455         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.455         # identical
2025-07-02 06:41:17.455
2025-07-02 06:41:17.455         # pump out diffs from before the synch point
2025-07-02 06:41:17.456         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.456
2025-07-02 06:41:17.456         # do intraline marking on the synch pair
2025-07-02 06:41:17.456         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.456         if eqi is None:
2025-07-02 06:41:17.456             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.456             atags = btags = ""
2025-07-02 06:41:17.456             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.456             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.456                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.456                 if tag == 'replace':
2025-07-02 06:41:17.456                     atags += '^' * la
2025-07-02 06:41:17.456                     btags += '^' * lb
2025-07-02 06:41:17.456                 elif tag == 'delete':
2025-07-02 06:41:17.456                     atags += '-' * la
2025-07-02 06:41:17.456                 elif tag == 'insert':
2025-07-02 06:41:17.456                     btags += '+' * lb
2025-07-02 06:41:17.456                 elif tag == 'equal':
2025-07-02 06:41:17.456                     atags += ' ' * la
2025-07-02 06:41:17.457                     btags += ' ' * lb
2025-07-02 06:41:17.457                 else:
2025-07-02 06:41:17.457                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.457             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.457         else:
2025-07-02 06:41:17.457             # the synch pair is identical
2025-07-02 06:41:17.457             yield '  ' + aelt
2025-07-02 06:41:17.457
2025-07-02 06:41:17.457         # pump out diffs from after the synch point
2025-07-02 06:41:17.457 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.457
2025-07-02 06:41:17.457 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.457 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.457
2025-07-02 06:41:17.457 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.457 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.457 alo = 233, ahi = 1101
2025-07-02 06:41:17.457 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.458 blo = 233, bhi = 1101
2025-07-02 06:41:17.458
2025-07-02 06:41:17.458     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.458         g = []
2025-07-02 06:41:17.458         if alo < ahi:
2025-07-02 06:41:17.458             if blo < bhi:
2025-07-02 06:41:17.458                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.458             else:
2025-07-02 06:41:17.458                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.458         elif blo < bhi:
2025-07-02 06:41:17.458             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.458
2025-07-02 06:41:17.458 >       yield from g
2025-07-02 06:41:17.458
2025-07-02 06:41:17.458 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.458 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.458
2025-07-02 06:41:17.458 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.458 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.459 alo = 233, ahi = 1101
2025-07-02 06:41:17.459 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.459 blo = 233, bhi = 1101
2025-07-02 06:41:17.459
2025-07-02 06:41:17.459     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.459         r"""
2025-07-02 06:41:17.459         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.459         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.459         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.459         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.459
2025-07-02 06:41:17.459         Example:
2025-07-02 06:41:17.459
2025-07-02 06:41:17.459         >>> d = Differ()
2025-07-02 06:41:17.459         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.459         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.459         >>> print(''.join(results), end="")
2025-07-02 06:41:17.459         - abcDefghiJkl
2025-07-02 06:41:17.460         + abcdefGhijkl
2025-07-02 06:41:17.460         """
2025-07-02 06:41:17.460
2025-07-02 06:41:17.460         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.460         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.460         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.460         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.460         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.460
2025-07-02 06:41:17.460         # search for the pair that matches best without being identical
2025-07-02 06:41:17.460         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.460         # on junk -- unless we have to)
2025-07-02 06:41:17.460         for j in range(blo, bhi):
2025-07-02 06:41:17.460             bj = b[j]
2025-07-02 06:41:17.460             cruncher.set_seq2(bj)
2025-07-02 06:41:17.460             for i in range(alo, ahi):
2025-07-02 06:41:17.460                 ai = a[i]
2025-07-02 06:41:17.461                 if ai == bj:
2025-07-02 06:41:17.461                     if eqi is None:
2025-07-02 06:41:17.461                         eqi, eqj = i, j
2025-07-02 06:41:17.461                     continue
2025-07-02 06:41:17.461                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.461                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.461                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.461                 # compares by a factor of 3.
2025-07-02 06:41:17.461                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.461                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.461                 # of the computation is cached by cruncher
2025-07-02 06:41:17.461                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.461                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.461                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.461                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.461         if best_ratio < cutoff:
2025-07-02 06:41:17.461             # no non-identical "pretty close" pair
2025-07-02 06:41:17.461             if eqi is None:
2025-07-02 06:41:17.461                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.461                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.462                 return
2025-07-02 06:41:17.462             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.462             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.462         else:
2025-07-02 06:41:17.462             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.462             eqi = None
2025-07-02 06:41:17.462
2025-07-02 06:41:17.462         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.462         # identical
2025-07-02 06:41:17.462
2025-07-02 06:41:17.462         # pump out diffs from before the synch point
2025-07-02 06:41:17.462         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.462
2025-07-02 06:41:17.462         # do intraline marking on the synch pair
2025-07-02 06:41:17.462         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.462         if eqi is None:
2025-07-02 06:41:17.462             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.462             atags = btags = ""
2025-07-02 06:41:17.463             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.463             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.463                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.463                 if tag == 'replace':
2025-07-02 06:41:17.463                     atags += '^' * la
2025-07-02 06:41:17.463                     btags += '^' * lb
2025-07-02 06:41:17.463                 elif tag == 'delete':
2025-07-02 06:41:17.463                     atags += '-' * la
2025-07-02 06:41:17.463                 elif tag == 'insert':
2025-07-02 06:41:17.463                     btags += '+' * lb
2025-07-02 06:41:17.463                 elif tag == 'equal':
2025-07-02 06:41:17.463                     atags += ' ' * la
2025-07-02 06:41:17.463                     btags += ' ' * lb
2025-07-02 06:41:17.463                 else:
2025-07-02 06:41:17.463                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.463             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.463         else:
2025-07-02 06:41:17.463             # the synch pair is identical
2025-07-02 06:41:17.463             yield '  ' + aelt
2025-07-02 06:41:17.463
2025-07-02 06:41:17.464         # pump out diffs from after the synch point
2025-07-02 06:41:17.464 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.464
2025-07-02 06:41:17.464 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.464 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.464
2025-07-02 06:41:17.464 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.464 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.464 alo = 234, ahi = 1101
2025-07-02 06:41:17.464 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.464 blo = 234, bhi = 1101
2025-07-02 06:41:17.464
2025-07-02 06:41:17.464     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.464         g = []
2025-07-02 06:41:17.464         if alo < ahi:
2025-07-02 06:41:17.464             if blo < bhi:
2025-07-02 06:41:17.464                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.464             else:
2025-07-02 06:41:17.464                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.465         elif blo < bhi:
2025-07-02 06:41:17.465             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.465
2025-07-02 06:41:17.465 >       yield from g
2025-07-02 06:41:17.465
2025-07-02 06:41:17.465 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.465 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.465
2025-07-02 06:41:17.465 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.465 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.465 alo = 234, ahi = 1101
2025-07-02 06:41:17.465 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.465 blo = 234, bhi = 1101
2025-07-02 06:41:17.465
2025-07-02 06:41:17.465     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.465         r"""
2025-07-02 06:41:17.465         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.465         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.465         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.466         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.466
2025-07-02 06:41:17.466         Example:
2025-07-02 06:41:17.466
2025-07-02 06:41:17.466         >>> d = Differ()
2025-07-02 06:41:17.466         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.466         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.466         >>> print(''.join(results), end="")
2025-07-02 06:41:17.466         - abcDefghiJkl
2025-07-02 06:41:17.466         + abcdefGhijkl
2025-07-02 06:41:17.466         """
2025-07-02 06:41:17.466
2025-07-02 06:41:17.466         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.466         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.466         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.466         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.466         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.466
2025-07-02 06:41:17.467         # search for the pair that matches best without being identical
2025-07-02 06:41:17.467         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.467         # on junk -- unless we have to)
2025-07-02 06:41:17.467         for j in range(blo, bhi):
2025-07-02 06:41:17.467             bj = b[j]
2025-07-02 06:41:17.467             cruncher.set_seq2(bj)
2025-07-02 06:41:17.467             for i in range(alo, ahi):
2025-07-02 06:41:17.467                 ai = a[i]
2025-07-02 06:41:17.467                 if ai == bj:
2025-07-02 06:41:17.467                     if eqi is None:
2025-07-02 06:41:17.467                         eqi, eqj = i, j
2025-07-02 06:41:17.467                     continue
2025-07-02 06:41:17.467                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.467                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.467                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.467                 # compares by a factor of 3.
2025-07-02 06:41:17.467                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.467                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.468                 # of the computation is cached by cruncher
2025-07-02 06:41:17.468                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.468                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.468                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.468                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.468         if best_ratio < cutoff:
2025-07-02 06:41:17.468             # no non-identical "pretty close" pair
2025-07-02 06:41:17.468             if eqi is None:
2025-07-02 06:41:17.468                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.468                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.468                 return
2025-07-02 06:41:17.468             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.468             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.468         else:
2025-07-02 06:41:17.468             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.468             eqi = None
2025-07-02 06:41:17.468
2025-07-02 06:41:17.468         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.468         # identical
2025-07-02 06:41:17.469
2025-07-02 06:41:17.469         # pump out diffs from before the synch point
2025-07-02 06:41:17.469         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.469
2025-07-02 06:41:17.469         # do intraline marking on the synch pair
2025-07-02 06:41:17.469         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.469         if eqi is None:
2025-07-02 06:41:17.469             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.469             atags = btags = ""
2025-07-02 06:41:17.469             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.469             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.469                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.469                 if tag == 'replace':
2025-07-02 06:41:17.469                     atags += '^' * la
2025-07-02 06:41:17.469                     btags += '^' * lb
2025-07-02 06:41:17.469                 elif tag == 'delete':
2025-07-02 06:41:17.469                     atags += '-' * la
2025-07-02 06:41:17.469                 elif tag == 'insert':
2025-07-02 06:41:17.469                     btags += '+' * lb
2025-07-02 06:41:17.470                 elif tag == 'equal':
2025-07-02 06:41:17.470                     atags += ' ' * la
2025-07-02 06:41:17.470                     btags += ' ' * lb
2025-07-02 06:41:17.470                 else:
2025-07-02 06:41:17.470                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.470             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.470         else:
2025-07-02 06:41:17.470             # the synch pair is identical
2025-07-02 06:41:17.470             yield '  ' + aelt
2025-07-02 06:41:17.470
2025-07-02 06:41:17.470         # pump out diffs from after the synch point
2025-07-02 06:41:17.470 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.470
2025-07-02 06:41:17.470 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.470 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.470
2025-07-02 06:41:17.470 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.470 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.470 alo = 235, ahi = 1101
2025-07-02 06:41:17.470 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.471 blo = 235, bhi = 1101
2025-07-02 06:41:17.471
2025-07-02 06:41:17.471     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.471         g = []
2025-07-02 06:41:17.471         if alo < ahi:
2025-07-02 06:41:17.471             if blo < bhi:
2025-07-02 06:41:17.471                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.471             else:
2025-07-02 06:41:17.471                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.471         elif blo < bhi:
2025-07-02 06:41:17.471             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.471
2025-07-02 06:41:17.471 >       yield from g
2025-07-02 06:41:17.471
2025-07-02 06:41:17.471 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.471 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.471
2025-07-02 06:41:17.471 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.471 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.472 alo = 235, ahi = 1101
2025-07-02 06:41:17.472 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.472 blo = 235, bhi = 1101
2025-07-02 06:41:17.472
2025-07-02 06:41:17.472     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.472         r"""
2025-07-02 06:41:17.472         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.472         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.472         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.472         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.472
2025-07-02 06:41:17.472         Example:
2025-07-02 06:41:17.472
2025-07-02 06:41:17.472         >>> d = Differ()
2025-07-02 06:41:17.472         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.472         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.472         >>> print(''.join(results), end="")
2025-07-02 06:41:17.472         - abcDefghiJkl
2025-07-02 06:41:17.473         + abcdefGhijkl
2025-07-02 06:41:17.473         """
2025-07-02 06:41:17.473
2025-07-02 06:41:17.473         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.473         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.473         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.473         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.473         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.473
2025-07-02 06:41:17.473         # search for the pair that matches best without being identical
2025-07-02 06:41:17.473         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.473         # on junk -- unless we have to)
2025-07-02 06:41:17.473         for j in range(blo, bhi):
2025-07-02 06:41:17.473             bj = b[j]
2025-07-02 06:41:17.473             cruncher.set_seq2(bj)
2025-07-02 06:41:17.473             for i in range(alo, ahi):
2025-07-02 06:41:17.473                 ai = a[i]
2025-07-02 06:41:17.474                 if ai == bj:
2025-07-02 06:41:17.474                     if eqi is None:
2025-07-02 06:41:17.474                         eqi, eqj = i, j
2025-07-02 06:41:17.474                     continue
2025-07-02 06:41:17.474                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.474                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.474                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.474                 # compares by a factor of 3.
2025-07-02 06:41:17.474                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.474                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.474                 # of the computation is cached by cruncher
2025-07-02 06:41:17.474                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.474                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.474                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.474                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.474         if best_ratio < cutoff:
2025-07-02 06:41:17.474             # no non-identical "pretty close" pair
2025-07-02 06:41:17.474             if eqi is None:
2025-07-02 06:41:17.475                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.475                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.475                 return
2025-07-02 06:41:17.475             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.475             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.475         else:
2025-07-02 06:41:17.475             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.475             eqi = None
2025-07-02 06:41:17.475
2025-07-02 06:41:17.475         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.475         # identical
2025-07-02 06:41:17.475
2025-07-02 06:41:17.475         # pump out diffs from before the synch point
2025-07-02 06:41:17.475         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.475
2025-07-02 06:41:17.475         # do intraline marking on the synch pair
2025-07-02 06:41:17.475         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.475         if eqi is None:
2025-07-02 06:41:17.475             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.476             atags = btags = ""
2025-07-02 06:41:17.476             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.476             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.476                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.476                 if tag == 'replace':
2025-07-02 06:41:17.476                     atags += '^' * la
2025-07-02 06:41:17.476                     btags += '^' * lb
2025-07-02 06:41:17.476                 elif tag == 'delete':
2025-07-02 06:41:17.476                     atags += '-' * la
2025-07-02 06:41:17.476                 elif tag == 'insert':
2025-07-02 06:41:17.476                     btags += '+' * lb
2025-07-02 06:41:17.476                 elif tag == 'equal':
2025-07-02 06:41:17.476                     atags += ' ' * la
2025-07-02 06:41:17.476                     btags += ' ' * lb
2025-07-02 06:41:17.476                 else:
2025-07-02 06:41:17.476                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.476             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.476         else:
2025-07-02 06:41:17.477             # the synch pair is identical
2025-07-02 06:41:17.477             yield '  ' + aelt
2025-07-02 06:41:17.477
2025-07-02 06:41:17.477         # pump out diffs from after the synch point
2025-07-02 06:41:17.477 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.477
2025-07-02 06:41:17.477 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.477 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.477
2025-07-02 06:41:17.477 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.477 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.477 alo = 236, ahi = 1101
2025-07-02 06:41:17.477 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.477 blo = 236, bhi = 1101
2025-07-02 06:41:17.477
2025-07-02 06:41:17.477     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.477         g = []
2025-07-02 06:41:17.477         if alo < ahi:
2025-07-02 06:41:17.478             if blo < bhi:
2025-07-02 06:41:17.478                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.478             else:
2025-07-02 06:41:17.478                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.478         elif blo < bhi:
2025-07-02 06:41:17.478             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.478
2025-07-02 06:41:17.478 >       yield from g
2025-07-02 06:41:17.478
2025-07-02 06:41:17.478 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.478 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.478
2025-07-02 06:41:17.478 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.478 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.478 alo = 236, ahi = 1101
2025-07-02 06:41:17.478 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.478 blo = 236, bhi = 1101
2025-07-02 06:41:17.478
2025-07-02 06:41:17.479     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.479         r"""
2025-07-02 06:41:17.479         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.479         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.479         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.479         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.479
2025-07-02 06:41:17.479         Example:
2025-07-02 06:41:17.479
2025-07-02 06:41:17.479         >>> d = Differ()
2025-07-02 06:41:17.479         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.479         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.479         >>> print(''.join(results), end="")
2025-07-02 06:41:17.479         - abcDefghiJkl
2025-07-02 06:41:17.479         + abcdefGhijkl
2025-07-02 06:41:17.479         """
2025-07-02 06:41:17.479
2025-07-02 06:41:17.480         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.480         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.480         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.480         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.480         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.480
2025-07-02 06:41:17.480         # search for the pair that matches best without being identical
2025-07-02 06:41:17.480         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.480         # on junk -- unless we have to)
2025-07-02 06:41:17.480         for j in range(blo, bhi):
2025-07-02 06:41:17.480             bj = b[j]
2025-07-02 06:41:17.480             cruncher.set_seq2(bj)
2025-07-02 06:41:17.480             for i in range(alo, ahi):
2025-07-02 06:41:17.480                 ai = a[i]
2025-07-02 06:41:17.480                 if ai == bj:
2025-07-02 06:41:17.480                     if eqi is None:
2025-07-02 06:41:17.480                         eqi, eqj = i, j
2025-07-02 06:41:17.480                     continue
2025-07-02 06:41:17.480                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.481                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.481                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.481                 # compares by a factor of 3.
2025-07-02 06:41:17.481                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.481                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.481                 # of the computation is cached by cruncher
2025-07-02 06:41:17.481                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.481                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.481                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.481                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.481         if best_ratio < cutoff:
2025-07-02 06:41:17.481             # no non-identical "pretty close" pair
2025-07-02 06:41:17.481             if eqi is None:
2025-07-02 06:41:17.481                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.481                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.481                 return
2025-07-02 06:41:17.481             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.481             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.482         else:
2025-07-02 06:41:17.482             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.482             eqi = None
2025-07-02 06:41:17.482
2025-07-02 06:41:17.482         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.482         # identical
2025-07-02 06:41:17.482
2025-07-02 06:41:17.482         # pump out diffs from before the synch point
2025-07-02 06:41:17.482         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.482
2025-07-02 06:41:17.482         # do intraline marking on the synch pair
2025-07-02 06:41:17.482         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.482         if eqi is None:
2025-07-02 06:41:17.482             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.482             atags = btags = ""
2025-07-02 06:41:17.482             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.482             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.482                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.482                 if tag == 'replace':
2025-07-02 06:41:17.483                     atags += '^' * la
2025-07-02 06:41:17.483                     btags += '^' * lb
2025-07-02 06:41:17.483                 elif tag == 'delete':
2025-07-02 06:41:17.483                     atags += '-' * la
2025-07-02 06:41:17.483                 elif tag == 'insert':
2025-07-02 06:41:17.483                     btags += '+' * lb
2025-07-02 06:41:17.483                 elif tag == 'equal':
2025-07-02 06:41:17.483                     atags += ' ' * la
2025-07-02 06:41:17.483                     btags += ' ' * lb
2025-07-02 06:41:17.483                 else:
2025-07-02 06:41:17.483                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.483             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.483         else:
2025-07-02 06:41:17.483             # the synch pair is identical
2025-07-02 06:41:17.483             yield '  ' + aelt
2025-07-02 06:41:17.483
2025-07-02 06:41:17.483         # pump out diffs from after the synch point
2025-07-02 06:41:17.483 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.483
2025-07-02 06:41:17.483 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.484 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.484
2025-07-02 06:41:17.484 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.484 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.484 alo = 237, ahi = 1101
2025-07-02 06:41:17.484 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.484 blo = 237, bhi = 1101
2025-07-02 06:41:17.484
2025-07-02 06:41:17.484     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.484         g = []
2025-07-02 06:41:17.484         if alo < ahi:
2025-07-02 06:41:17.484             if blo < bhi:
2025-07-02 06:41:17.484                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.484             else:
2025-07-02 06:41:17.484                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.484         elif blo < bhi:
2025-07-02 06:41:17.484             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.484
2025-07-02 06:41:17.485 >       yield from g
2025-07-02 06:41:17.485
2025-07-02 06:41:17.485 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.485 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.485
2025-07-02 06:41:17.485 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.485 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.485 alo = 237, ahi = 1101
2025-07-02 06:41:17.485 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.485 blo = 237, bhi = 1101
2025-07-02 06:41:17.485
2025-07-02 06:41:17.485     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.485         r"""
2025-07-02 06:41:17.485         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.485         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.485         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.485         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.486
2025-07-02 06:41:17.486         Example:
2025-07-02 06:41:17.486
2025-07-02 06:41:17.486         >>> d = Differ()
2025-07-02 06:41:17.486         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.486         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.486         >>> print(''.join(results), end="")
2025-07-02 06:41:17.486         - abcDefghiJkl
2025-07-02 06:41:17.486         + abcdefGhijkl
2025-07-02 06:41:17.486         """
2025-07-02 06:41:17.486
2025-07-02 06:41:17.486         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.486         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.486         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.486         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.486         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.486
2025-07-02 06:41:17.487         # search for the pair that matches best without being identical
2025-07-02 06:41:17.487         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.487         # on junk -- unless we have to)
2025-07-02 06:41:17.487         for j in range(blo, bhi):
2025-07-02 06:41:17.487             bj = b[j]
2025-07-02 06:41:17.487             cruncher.set_seq2(bj)
2025-07-02 06:41:17.487             for i in range(alo, ahi):
2025-07-02 06:41:17.487                 ai = a[i]
2025-07-02 06:41:17.487                 if ai == bj:
2025-07-02 06:41:17.487                     if eqi is None:
2025-07-02 06:41:17.487                         eqi, eqj = i, j
2025-07-02 06:41:17.487                     continue
2025-07-02 06:41:17.487                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.487                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.487                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.487                 # compares by a factor of 3.
2025-07-02 06:41:17.487                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.487                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.487                 # of the computation is cached by cruncher
2025-07-02 06:41:17.488                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.488                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.488                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.488                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.488         if best_ratio < cutoff:
2025-07-02 06:41:17.488             # no non-identical "pretty close" pair
2025-07-02 06:41:17.488             if eqi is None:
2025-07-02 06:41:17.488                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.488                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.488                 return
2025-07-02 06:41:17.488             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.488             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.488         else:
2025-07-02 06:41:17.488             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.488             eqi = None
2025-07-02 06:41:17.488
2025-07-02 06:41:17.488         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.488         # identical
2025-07-02 06:41:17.488
2025-07-02 06:41:17.488         # pump out diffs from before the synch point
2025-07-02 06:41:17.489         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.489
2025-07-02 06:41:17.489         # do intraline marking on the synch pair
2025-07-02 06:41:17.489         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.489         if eqi is None:
2025-07-02 06:41:17.489             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.489             atags = btags = ""
2025-07-02 06:41:17.489             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.489             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.489                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.489                 if tag == 'replace':
2025-07-02 06:41:17.489                     atags += '^' * la
2025-07-02 06:41:17.489                     btags += '^' * lb
2025-07-02 06:41:17.489                 elif tag == 'delete':
2025-07-02 06:41:17.489                     atags += '-' * la
2025-07-02 06:41:17.489                 elif tag == 'insert':
2025-07-02 06:41:17.489                     btags += '+' * lb
2025-07-02 06:41:17.490                 elif tag == 'equal':
2025-07-02 06:41:17.490                     atags += ' ' * la
2025-07-02 06:41:17.490                     btags += ' ' * lb
2025-07-02 06:41:17.490                 else:
2025-07-02 06:41:17.490                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.490             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.490         else:
2025-07-02 06:41:17.490             # the synch pair is identical
2025-07-02 06:41:17.490             yield '  ' + aelt
2025-07-02 06:41:17.490
2025-07-02 06:41:17.490         # pump out diffs from after the synch point
2025-07-02 06:41:17.490 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.490
2025-07-02 06:41:17.490 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.490 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.490
2025-07-02 06:41:17.490 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.490 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.490 alo = 238, ahi = 1101
2025-07-02 06:41:17.491 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.491 blo = 238, bhi = 1101
2025-07-02 06:41:17.491
2025-07-02 06:41:17.491     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.491         g = []
2025-07-02 06:41:17.491         if alo < ahi:
2025-07-02 06:41:17.491             if blo < bhi:
2025-07-02 06:41:17.491                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.491             else:
2025-07-02 06:41:17.491                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.491         elif blo < bhi:
2025-07-02 06:41:17.491             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.491
2025-07-02 06:41:17.491 >       yield from g
2025-07-02 06:41:17.491
2025-07-02 06:41:17.491 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.491 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.492
2025-07-02 06:41:17.492 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.492 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.492 alo = 238, ahi = 1101
2025-07-02 06:41:17.492 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.492 blo = 238, bhi = 1101
2025-07-02 06:41:17.492
2025-07-02 06:41:17.492     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.492         r"""
2025-07-02 06:41:17.492         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.492         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.492         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.492         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.492
2025-07-02 06:41:17.492         Example:
2025-07-02 06:41:17.492
2025-07-02 06:41:17.492         >>> d = Differ()
2025-07-02 06:41:17.492         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.493         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.493         >>> print(''.join(results), end="")
2025-07-02 06:41:17.493         - abcDefghiJkl
2025-07-02 06:41:17.493         + abcdefGhijkl
2025-07-02 06:41:17.493         """
2025-07-02 06:41:17.493
2025-07-02 06:41:17.493         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.493         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.493         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.493         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.493         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.493
2025-07-02 06:41:17.493         # search for the pair that matches best without being identical
2025-07-02 06:41:17.493         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.493         # on junk -- unless we have to)
2025-07-02 06:41:17.493         for j in range(blo, bhi):
2025-07-02 06:41:17.493             bj = b[j]
2025-07-02 06:41:17.494             cruncher.set_seq2(bj)
2025-07-02 06:41:17.494             for i in range(alo, ahi):
2025-07-02 06:41:17.494                 ai = a[i]
2025-07-02 06:41:17.494                 if ai == bj:
2025-07-02 06:41:17.494                     if eqi is None:
2025-07-02 06:41:17.494                         eqi, eqj = i, j
2025-07-02 06:41:17.494                     continue
2025-07-02 06:41:17.494                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.494                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.494                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.494                 # compares by a factor of 3.
2025-07-02 06:41:17.494                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.494                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.494                 # of the computation is cached by cruncher
2025-07-02 06:41:17.494                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.494                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.494                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.495                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.495         if best_ratio < cutoff:
2025-07-02 06:41:17.495             # no non-identical "pretty close" pair
2025-07-02 06:41:17.495             if eqi is None:
2025-07-02 06:41:17.495                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.495                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.495                 return
2025-07-02 06:41:17.495             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.495             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.495         else:
2025-07-02 06:41:17.495             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.495             eqi = None
2025-07-02 06:41:17.495
2025-07-02 06:41:17.495         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.495         # identical
2025-07-02 06:41:17.495
2025-07-02 06:41:17.495         # pump out diffs from before the synch point
2025-07-02 06:41:17.496         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.496
2025-07-02 06:41:17.496         # do intraline marking on the synch pair
2025-07-02 06:41:17.496         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.496         if eqi is None:
2025-07-02 06:41:17.496             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.496             atags = btags = ""
2025-07-02 06:41:17.496             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.496             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.496                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.496                 if tag == 'replace':
2025-07-02 06:41:17.496                     atags += '^' * la
2025-07-02 06:41:17.496                     btags += '^' * lb
2025-07-02 06:41:17.496                 elif tag == 'delete':
2025-07-02 06:41:17.496                     atags += '-' * la
2025-07-02 06:41:17.496                 elif tag == 'insert':
2025-07-02 06:41:17.496                     btags += '+' * lb
2025-07-02 06:41:17.496                 elif tag == 'equal':
2025-07-02 06:41:17.497                     atags += ' ' * la
2025-07-02 06:41:17.497                     btags += ' ' * lb
2025-07-02 06:41:17.497                 else:
2025-07-02 06:41:17.497                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.497             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.497         else:
2025-07-02 06:41:17.497             # the synch pair is identical
2025-07-02 06:41:17.497             yield '  ' + aelt
2025-07-02 06:41:17.497
2025-07-02 06:41:17.497         # pump out diffs from after the synch point
2025-07-02 06:41:17.497 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.497
2025-07-02 06:41:17.497 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.497 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.497
2025-07-02 06:41:17.497 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.497 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.497 alo = 239, ahi = 1101
2025-07-02 06:41:17.497 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.498 blo = 239, bhi = 1101
2025-07-02 06:41:17.498
2025-07-02 06:41:17.498     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.498         g = []
2025-07-02 06:41:17.498         if alo < ahi:
2025-07-02 06:41:17.498             if blo < bhi:
2025-07-02 06:41:17.498                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.498             else:
2025-07-02 06:41:17.498                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.498         elif blo < bhi:
2025-07-02 06:41:17.498             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.498
2025-07-02 06:41:17.498 >       yield from g
2025-07-02 06:41:17.498
2025-07-02 06:41:17.498 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.498 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.498
2025-07-02 06:41:17.498 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.498 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.499 alo = 239, ahi = 1101
2025-07-02 06:41:17.499 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.499 blo = 239, bhi = 1101
2025-07-02 06:41:17.499
2025-07-02 06:41:17.499     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.499         r"""
2025-07-02 06:41:17.499         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.499         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.499         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.499         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.499
2025-07-02 06:41:17.499         Example:
2025-07-02 06:41:17.499
2025-07-02 06:41:17.499         >>> d = Differ()
2025-07-02 06:41:17.499         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.499         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.499         >>> print(''.join(results), end="")
2025-07-02 06:41:17.499         - abcDefghiJkl
2025-07-02 06:41:17.500         + abcdefGhijkl
2025-07-02 06:41:17.500         """
2025-07-02 06:41:17.500
2025-07-02 06:41:17.500         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.500         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.500         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.500         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.500         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.500
2025-07-02 06:41:17.500         # search for the pair that matches best without being identical
2025-07-02 06:41:17.500         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.500         # on junk -- unless we have to)
2025-07-02 06:41:17.500         for j in range(blo, bhi):
2025-07-02 06:41:17.500             bj = b[j]
2025-07-02 06:41:17.500             cruncher.set_seq2(bj)
2025-07-02 06:41:17.500             for i in range(alo, ahi):
2025-07-02 06:41:17.500                 ai = a[i]
2025-07-02 06:41:17.500                 if ai == bj:
2025-07-02 06:41:17.500                     if eqi is None:
2025-07-02 06:41:17.501                         eqi, eqj = i, j
2025-07-02 06:41:17.501                     continue
2025-07-02 06:41:17.501                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.501                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.501                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.501                 # compares by a factor of 3.
2025-07-02 06:41:17.501                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.501                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.501                 # of the computation is cached by cruncher
2025-07-02 06:41:17.501                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.501                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.501                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.501                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.501         if best_ratio < cutoff:
2025-07-02 06:41:17.501             # no non-identical "pretty close" pair
2025-07-02 06:41:17.501             if eqi is None:
2025-07-02 06:41:17.501                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.501                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.501                 return
2025-07-02 06:41:17.501             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.502             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.502         else:
2025-07-02 06:41:17.502             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.502             eqi = None
2025-07-02 06:41:17.502
2025-07-02 06:41:17.502         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.502         # identical
2025-07-02 06:41:17.502
2025-07-02 06:41:17.502         # pump out diffs from before the synch point
2025-07-02 06:41:17.502         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.502
2025-07-02 06:41:17.502         # do intraline marking on the synch pair
2025-07-02 06:41:17.502         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.502         if eqi is None:
2025-07-02 06:41:17.502             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.502             atags = btags = ""
2025-07-02 06:41:17.502             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.502             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.502                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.503                 if tag == 'replace':
2025-07-02 06:41:17.503                     atags += '^' * la
2025-07-02 06:41:17.503                     btags += '^' * lb
2025-07-02 06:41:17.503                 elif tag == 'delete':
2025-07-02 06:41:17.503                     atags += '-' * la
2025-07-02 06:41:17.503                 elif tag == 'insert':
2025-07-02 06:41:17.503                     btags += '+' * lb
2025-07-02 06:41:17.503                 elif tag == 'equal':
2025-07-02 06:41:17.503                     atags += ' ' * la
2025-07-02 06:41:17.503                     btags += ' ' * lb
2025-07-02 06:41:17.503                 else:
2025-07-02 06:41:17.503                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.503             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.503         else:
2025-07-02 06:41:17.503             # the synch pair is identical
2025-07-02 06:41:17.503             yield '  ' + aelt
2025-07-02 06:41:17.503
2025-07-02 06:41:17.503         # pump out diffs from after the synch point
2025-07-02 06:41:17.503 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.503
2025-07-02 06:41:17.504 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.504 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.504
2025-07-02 06:41:17.504 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.504 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.504 alo = 240, ahi = 1101
2025-07-02 06:41:17.504 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.504 blo = 240, bhi = 1101
2025-07-02 06:41:17.504
2025-07-02 06:41:17.504     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.504         g = []
2025-07-02 06:41:17.504         if alo < ahi:
2025-07-02 06:41:17.504             if blo < bhi:
2025-07-02 06:41:17.504                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.504             else:
2025-07-02 06:41:17.504                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.504         elif blo < bhi:
2025-07-02 06:41:17.504             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.505
2025-07-02 06:41:17.505 >       yield from g
2025-07-02 06:41:17.505
2025-07-02 06:41:17.505 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.505 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.505
2025-07-02 06:41:17.505 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.505 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.505 alo = 240, ahi = 1101
2025-07-02 06:41:17.505 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.505 blo = 240, bhi = 1101
2025-07-02 06:41:17.505
2025-07-02 06:41:17.505     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.505         r"""
2025-07-02 06:41:17.505         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.505         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.505         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.506         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.506
2025-07-02 06:41:17.506         Example:
2025-07-02 06:41:17.506
2025-07-02 06:41:17.506         >>> d = Differ()
2025-07-02 06:41:17.506         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.506         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.506         >>> print(''.join(results), end="")
2025-07-02 06:41:17.506         - abcDefghiJkl
2025-07-02 06:41:17.506         + abcdefGhijkl
2025-07-02 06:41:17.506         """
2025-07-02 06:41:17.506
2025-07-02 06:41:17.506         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.506         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.506         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.506         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.506         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.507
2025-07-02 06:41:17.507         # search for the pair that matches best without being identical
2025-07-02 06:41:17.507         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.507         # on junk -- unless we have to)
2025-07-02 06:41:17.507         for j in range(blo, bhi):
2025-07-02 06:41:17.507             bj = b[j]
2025-07-02 06:41:17.507             cruncher.set_seq2(bj)
2025-07-02 06:41:17.507             for i in range(alo, ahi):
2025-07-02 06:41:17.507                 ai = a[i]
2025-07-02 06:41:17.507                 if ai == bj:
2025-07-02 06:41:17.507                     if eqi is None:
2025-07-02 06:41:17.507                         eqi, eqj = i, j
2025-07-02 06:41:17.507                     continue
2025-07-02 06:41:17.507                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.507                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.507                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.507                 # compares by a factor of 3.
2025-07-02 06:41:17.507                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.507                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.508                 # of the computation is cached by cruncher
2025-07-02 06:41:17.508                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.508                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.508                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.508                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.508         if best_ratio < cutoff:
2025-07-02 06:41:17.508             # no non-identical "pretty close" pair
2025-07-02 06:41:17.508             if eqi is None:
2025-07-02 06:41:17.508                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.508                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.508                 return
2025-07-02 06:41:17.508             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.508             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.508         else:
2025-07-02 06:41:17.508             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.508             eqi = None
2025-07-02 06:41:17.508
2025-07-02 06:41:17.508         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.509         # identical
2025-07-02 06:41:17.509
2025-07-02 06:41:17.509         # pump out diffs from before the synch point
2025-07-02 06:41:17.509         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.509
2025-07-02 06:41:17.509         # do intraline marking on the synch pair
2025-07-02 06:41:17.509         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.509         if eqi is None:
2025-07-02 06:41:17.509             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.509             atags = btags = ""
2025-07-02 06:41:17.509             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.509             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.509                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.509                 if tag == 'replace':
2025-07-02 06:41:17.509                     atags += '^' * la
2025-07-02 06:41:17.509                     btags += '^' * lb
2025-07-02 06:41:17.509                 elif tag == 'delete':
2025-07-02 06:41:17.509                     atags += '-' * la
2025-07-02 06:41:17.509                 elif tag == 'insert':
2025-07-02 06:41:17.510                     btags += '+' * lb
2025-07-02 06:41:17.510                 elif tag == 'equal':
2025-07-02 06:41:17.510                     atags += ' ' * la
2025-07-02 06:41:17.510                     btags += ' ' * lb
2025-07-02 06:41:17.510                 else:
2025-07-02 06:41:17.510                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.510             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.510         else:
2025-07-02 06:41:17.510             # the synch pair is identical
2025-07-02 06:41:17.510             yield '  ' + aelt
2025-07-02 06:41:17.510
2025-07-02 06:41:17.510         # pump out diffs from after the synch point
2025-07-02 06:41:17.510 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.510
2025-07-02 06:41:17.510 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.510 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.510
2025-07-02 06:41:17.510 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.510 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.511 alo = 241, ahi = 1101
2025-07-02 06:41:17.511 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.511 blo = 241, bhi = 1101
2025-07-02 06:41:17.511
2025-07-02 06:41:17.511     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.511         g = []
2025-07-02 06:41:17.511         if alo < ahi:
2025-07-02 06:41:17.511             if blo < bhi:
2025-07-02 06:41:17.511                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.511             else:
2025-07-02 06:41:17.511                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.511         elif blo < bhi:
2025-07-02 06:41:17.511             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.511
2025-07-02 06:41:17.511 >       yield from g
2025-07-02 06:41:17.511
2025-07-02 06:41:17.511 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.511 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.511
2025-07-02 06:41:17.512 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.512 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.512 alo = 241, ahi = 1101
2025-07-02 06:41:17.512 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.512 blo = 241, bhi = 1101
2025-07-02 06:41:17.512
2025-07-02 06:41:17.512     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.512         r"""
2025-07-02 06:41:17.512         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.512         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.512         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.512         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.512
2025-07-02 06:41:17.512         Example:
2025-07-02 06:41:17.512
2025-07-02 06:41:17.512         >>> d = Differ()
2025-07-02 06:41:17.512         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.512         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.513         >>> print(''.join(results), end="")
2025-07-02 06:41:17.513         - abcDefghiJkl
2025-07-02 06:41:17.513         + abcdefGhijkl
2025-07-02 06:41:17.513         """
2025-07-02 06:41:17.513
2025-07-02 06:41:17.513         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.513         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.513         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.513         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.513         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.513
2025-07-02 06:41:17.513         # search for the pair that matches best without being identical
2025-07-02 06:41:17.513         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.513         # on junk -- unless we have to)
2025-07-02 06:41:17.513         for j in range(blo, bhi):
2025-07-02 06:41:17.514             bj = b[j]
2025-07-02 06:41:17.514             cruncher.set_seq2(bj)
2025-07-02 06:41:17.514             for i in range(alo, ahi):
2025-07-02 06:41:17.514                 ai = a[i]
2025-07-02 06:41:17.514                 if ai == bj:
2025-07-02 06:41:17.514                     if eqi is None:
2025-07-02 06:41:17.514                         eqi, eqj = i, j
2025-07-02 06:41:17.514                     continue
2025-07-02 06:41:17.514                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.514                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.514                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.514                 # compares by a factor of 3.
2025-07-02 06:41:17.514                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.514                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.514                 # of the computation is cached by cruncher
2025-07-02 06:41:17.514                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.514                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.514                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.514                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.515         if best_ratio < cutoff:
2025-07-02 06:41:17.515             # no non-identical "pretty close" pair
2025-07-02 06:41:17.515             if eqi is None:
2025-07-02 06:41:17.515                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.515                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.515                 return
2025-07-02 06:41:17.515             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.515             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.515         else:
2025-07-02 06:41:17.515             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.515             eqi = None
2025-07-02 06:41:17.515
2025-07-02 06:41:17.515         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.515         # identical
2025-07-02 06:41:17.515
2025-07-02 06:41:17.515         # pump out diffs from before the synch point
2025-07-02 06:41:17.515         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.515
2025-07-02 06:41:17.516         # do intraline marking on the synch pair
2025-07-02 06:41:17.516         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.516         if eqi is None:
2025-07-02 06:41:17.516             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.516             atags = btags = ""
2025-07-02 06:41:17.516             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.516             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.516                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.516                 if tag == 'replace':
2025-07-02 06:41:17.516                     atags += '^' * la
2025-07-02 06:41:17.516                     btags += '^' * lb
2025-07-02 06:41:17.516                 elif tag == 'delete':
2025-07-02 06:41:17.516                     atags += '-' * la
2025-07-02 06:41:17.516                 elif tag == 'insert':
2025-07-02 06:41:17.516                     btags += '+' * lb
2025-07-02 06:41:17.516                 elif tag == 'equal':
2025-07-02 06:41:17.516                     atags += ' ' * la
2025-07-02 06:41:17.516                     btags += ' ' * lb
2025-07-02 06:41:17.516                 else:
2025-07-02 06:41:17.516                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.517             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.517         else:
2025-07-02 06:41:17.517             # the synch pair is identical
2025-07-02 06:41:17.517             yield '  ' + aelt
2025-07-02 06:41:17.517
2025-07-02 06:41:17.517         # pump out diffs from after the synch point
2025-07-02 06:41:17.517 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.517
2025-07-02 06:41:17.517 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.517 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.517
2025-07-02 06:41:17.517 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.517 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.517 alo = 242, ahi = 1101
2025-07-02 06:41:17.517 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.517 blo = 242, bhi = 1101
2025-07-02 06:41:17.517
2025-07-02 06:41:17.517     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.517         g = []
2025-07-02 06:41:17.518         if alo < ahi:
2025-07-02 06:41:17.518             if blo < bhi:
2025-07-02 06:41:17.518                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.518             else:
2025-07-02 06:41:17.518                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.518         elif blo < bhi:
2025-07-02 06:41:17.518             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.518
2025-07-02 06:41:17.518 >       yield from g
2025-07-02 06:41:17.518
2025-07-02 06:41:17.518 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.518 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.518
2025-07-02 06:41:17.518 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.518 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.518 alo = 242, ahi = 1101
2025-07-02 06:41:17.518 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.518 blo = 242, bhi = 1101
2025-07-02 06:41:17.518
2025-07-02 06:41:17.519     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.519         r"""
2025-07-02 06:41:17.519         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.519         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.519         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.519         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.519
2025-07-02 06:41:17.519         Example:
2025-07-02 06:41:17.519
2025-07-02 06:41:17.519         >>> d = Differ()
2025-07-02 06:41:17.519         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.519         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.519         >>> print(''.join(results), end="")
2025-07-02 06:41:17.519         - abcDefghiJkl
2025-07-02 06:41:17.519         + abcdefGhijkl
2025-07-02 06:41:17.519         """
2025-07-02 06:41:17.519
2025-07-02 06:41:17.519         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.520         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.520         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.520         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.520         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.520
2025-07-02 06:41:17.520         # search for the pair that matches best without being identical
2025-07-02 06:41:17.520         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.520         # on junk -- unless we have to)
2025-07-02 06:41:17.520         for j in range(blo, bhi):
2025-07-02 06:41:17.520             bj = b[j]
2025-07-02 06:41:17.520             cruncher.set_seq2(bj)
2025-07-02 06:41:17.520             for i in range(alo, ahi):
2025-07-02 06:41:17.520                 ai = a[i]
2025-07-02 06:41:17.520                 if ai == bj:
2025-07-02 06:41:17.520                     if eqi is None:
2025-07-02 06:41:17.520                         eqi, eqj = i, j
2025-07-02 06:41:17.520                     continue
2025-07-02 06:41:17.520                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.520                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.520                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.521                 # compares by a factor of 3.
2025-07-02 06:41:17.521                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.521                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.521                 # of the computation is cached by cruncher
2025-07-02 06:41:17.521                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.521                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.521                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.521                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.521         if best_ratio < cutoff:
2025-07-02 06:41:17.521             # no non-identical "pretty close" pair
2025-07-02 06:41:17.521             if eqi is None:
2025-07-02 06:41:17.521                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.521                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.521                 return
2025-07-02 06:41:17.521             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.521             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.521         else:
2025-07-02 06:41:17.521             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.522             eqi = None
2025-07-02 06:41:17.522
2025-07-02 06:41:17.522         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.522         # identical
2025-07-02 06:41:17.522
2025-07-02 06:41:17.522         # pump out diffs from before the synch point
2025-07-02 06:41:17.522         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.522
2025-07-02 06:41:17.522         # do intraline marking on the synch pair
2025-07-02 06:41:17.522         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.522         if eqi is None:
2025-07-02 06:41:17.522             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.522             atags = btags = ""
2025-07-02 06:41:17.522             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.522             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.522                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.522                 if tag == 'replace':
2025-07-02 06:41:17.523                     atags += '^' * la
2025-07-02 06:41:17.523                     btags += '^' * lb
2025-07-02 06:41:17.523                 elif tag == 'delete':
2025-07-02 06:41:17.523                     atags += '-' * la
2025-07-02 06:41:17.523                 elif tag == 'insert':
2025-07-02 06:41:17.523                     btags += '+' * lb
2025-07-02 06:41:17.523                 elif tag == 'equal':
2025-07-02 06:41:17.523                     atags += ' ' * la
2025-07-02 06:41:17.523                     btags += ' ' * lb
2025-07-02 06:41:17.523                 else:
2025-07-02 06:41:17.523                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.523             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.523         else:
2025-07-02 06:41:17.523             # the synch pair is identical
2025-07-02 06:41:17.523             yield '  ' + aelt
2025-07-02 06:41:17.523
2025-07-02 06:41:17.523         # pump out diffs from after the synch point
2025-07-02 06:41:17.523 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.523
2025-07-02 06:41:17.524 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.524 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.524
2025-07-02 06:41:17.524 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.524 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.524 alo = 243, ahi = 1101
2025-07-02 06:41:17.524 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.524 blo = 243, bhi = 1101
2025-07-02 06:41:17.524
2025-07-02 06:41:17.524     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.524         g = []
2025-07-02 06:41:17.524         if alo < ahi:
2025-07-02 06:41:17.524             if blo < bhi:
2025-07-02 06:41:17.524                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.524             else:
2025-07-02 06:41:17.524                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.524         elif blo < bhi:
2025-07-02 06:41:17.524             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.524
2025-07-02 06:41:17.525 >       yield from g
2025-07-02 06:41:17.525
2025-07-02 06:41:17.525 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.525 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.525
2025-07-02 06:41:17.525 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.525 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.525 alo = 243, ahi = 1101
2025-07-02 06:41:17.525 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.525 blo = 243, bhi = 1101
2025-07-02 06:41:17.525
2025-07-02 06:41:17.525     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.525         r"""
2025-07-02 06:41:17.525         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.525         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.525         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.525         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.525
2025-07-02 06:41:17.525         Example:
2025-07-02 06:41:17.526
2025-07-02 06:41:17.526         >>> d = Differ()
2025-07-02 06:41:17.526         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.526         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.526         >>> print(''.join(results), end="")
2025-07-02 06:41:17.526         - abcDefghiJkl
2025-07-02 06:41:17.526         + abcdefGhijkl
2025-07-02 06:41:17.526         """
2025-07-02 06:41:17.526
2025-07-02 06:41:17.526         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.526         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.526         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.526         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.526         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.526
2025-07-02 06:41:17.526         # search for the pair that matches best without being identical
2025-07-02 06:41:17.526         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.526         # on junk -- unless we have to)
2025-07-02 06:41:17.527         for j in range(blo, bhi):
2025-07-02 06:41:17.527             bj = b[j]
2025-07-02 06:41:17.527             cruncher.set_seq2(bj)
2025-07-02 06:41:17.527             for i in range(alo, ahi):
2025-07-02 06:41:17.527                 ai = a[i]
2025-07-02 06:41:17.527                 if ai == bj:
2025-07-02 06:41:17.527                     if eqi is None:
2025-07-02 06:41:17.527                         eqi, eqj = i, j
2025-07-02 06:41:17.527                     continue
2025-07-02 06:41:17.527                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.527                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.527                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.527                 # compares by a factor of 3.
2025-07-02 06:41:17.527                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.527                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.527                 # of the computation is cached by cruncher
2025-07-02 06:41:17.527                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.527                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.527                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.528                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.528         if best_ratio < cutoff:
2025-07-02 06:41:17.528             # no non-identical "pretty close" pair
2025-07-02 06:41:17.528             if eqi is None:
2025-07-02 06:41:17.528                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.528                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.528                 return
2025-07-02 06:41:17.528             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.528             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.528         else:
2025-07-02 06:41:17.528             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.528             eqi = None
2025-07-02 06:41:17.528
2025-07-02 06:41:17.528         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.528         # identical
2025-07-02 06:41:17.528
2025-07-02 06:41:17.528         # pump out diffs from before the synch point
2025-07-02 06:41:17.528         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.528
2025-07-02 06:41:17.528         # do intraline marking on the synch pair
2025-07-02 06:41:17.529         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.529         if eqi is None:
2025-07-02 06:41:17.529             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.529             atags = btags = ""
2025-07-02 06:41:17.529             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.529             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.529                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.529                 if tag == 'replace':
2025-07-02 06:41:17.529                     atags += '^' * la
2025-07-02 06:41:17.529                     btags += '^' * lb
2025-07-02 06:41:17.529                 elif tag == 'delete':
2025-07-02 06:41:17.529                     atags += '-' * la
2025-07-02 06:41:17.529                 elif tag == 'insert':
2025-07-02 06:41:17.529                     btags += '+' * lb
2025-07-02 06:41:17.529                 elif tag == 'equal':
2025-07-02 06:41:17.529                     atags += ' ' * la
2025-07-02 06:41:17.529                     btags += ' ' * lb
2025-07-02 06:41:17.529                 else:
2025-07-02 06:41:17.529                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.530             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.530         else:
2025-07-02 06:41:17.530             # the synch pair is identical
2025-07-02 06:41:17.530             yield '  ' + aelt
2025-07-02 06:41:17.530
2025-07-02 06:41:17.530         # pump out diffs from after the synch point
2025-07-02 06:41:17.530 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.530
2025-07-02 06:41:17.530 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.530 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.530
2025-07-02 06:41:17.530 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.530 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.530 alo = 246, ahi = 1101
2025-07-02 06:41:17.530 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.530 blo = 246, bhi = 1101
2025-07-02 06:41:17.530
2025-07-02 06:41:17.530     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.530         g = []
2025-07-02 06:41:17.530         if alo < ahi:
2025-07-02 06:41:17.531             if blo < bhi:
2025-07-02 06:41:17.531                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.531             else:
2025-07-02 06:41:17.531                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.531         elif blo < bhi:
2025-07-02 06:41:17.531             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.531
2025-07-02 06:41:17.531 >       yield from g
2025-07-02 06:41:17.531
2025-07-02 06:41:17.531 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.531 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.531
2025-07-02 06:41:17.531 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.531 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.531 alo = 246, ahi = 1101
2025-07-02 06:41:17.531 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.531 blo = 246, bhi = 1101
2025-07-02 06:41:17.531
2025-07-02 06:41:17.532     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.532         r"""
2025-07-02 06:41:17.532         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.532         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.532         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.532         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.532
2025-07-02 06:41:17.532         Example:
2025-07-02 06:41:17.532
2025-07-02 06:41:17.532         >>> d = Differ()
2025-07-02 06:41:17.532         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.532         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.532         >>> print(''.join(results), end="")
2025-07-02 06:41:17.532         - abcDefghiJkl
2025-07-02 06:41:17.532         + abcdefGhijkl
2025-07-02 06:41:17.532         """
2025-07-02 06:41:17.532
2025-07-02 06:41:17.533         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.533         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.533         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.533         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.533         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.533
2025-07-02 06:41:17.533         # search for the pair that matches best without being identical
2025-07-02 06:41:17.533         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.533         # on junk -- unless we have to)
2025-07-02 06:41:17.533         for j in range(blo, bhi):
2025-07-02 06:41:17.533             bj = b[j]
2025-07-02 06:41:17.533             cruncher.set_seq2(bj)
2025-07-02 06:41:17.533             for i in range(alo, ahi):
2025-07-02 06:41:17.533                 ai = a[i]
2025-07-02 06:41:17.533                 if ai == bj:
2025-07-02 06:41:17.533                     if eqi is None:
2025-07-02 06:41:17.533                         eqi, eqj = i, j
2025-07-02 06:41:17.533                     continue
2025-07-02 06:41:17.533                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.534                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.534                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.534                 # compares by a factor of 3.
2025-07-02 06:41:17.534                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.534                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.534                 # of the computation is cached by cruncher
2025-07-02 06:41:17.534                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.534                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.534                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.534                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.534         if best_ratio < cutoff:
2025-07-02 06:41:17.534             # no non-identical "pretty close" pair
2025-07-02 06:41:17.534             if eqi is None:
2025-07-02 06:41:17.534                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.534                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.534                 return
2025-07-02 06:41:17.534             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.534             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.534         else:
2025-07-02 06:41:17.534             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.535             eqi = None
2025-07-02 06:41:17.535
2025-07-02 06:41:17.535         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.535         # identical
2025-07-02 06:41:17.535
2025-07-02 06:41:17.535         # pump out diffs from before the synch point
2025-07-02 06:41:17.535         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.535
2025-07-02 06:41:17.535         # do intraline marking on the synch pair
2025-07-02 06:41:17.535         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.535         if eqi is None:
2025-07-02 06:41:17.535             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.535             atags = btags = ""
2025-07-02 06:41:17.535             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.535             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.535                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.535                 if tag == 'replace':
2025-07-02 06:41:17.535                     atags += '^' * la
2025-07-02 06:41:17.536                     btags += '^' * lb
2025-07-02 06:41:17.536                 elif tag == 'delete':
2025-07-02 06:41:17.536                     atags += '-' * la
2025-07-02 06:41:17.536                 elif tag == 'insert':
2025-07-02 06:41:17.536                     btags += '+' * lb
2025-07-02 06:41:17.536                 elif tag == 'equal':
2025-07-02 06:41:17.536                     atags += ' ' * la
2025-07-02 06:41:17.536                     btags += ' ' * lb
2025-07-02 06:41:17.536                 else:
2025-07-02 06:41:17.536                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.536             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.536         else:
2025-07-02 06:41:17.536             # the synch pair is identical
2025-07-02 06:41:17.536             yield '  ' + aelt
2025-07-02 06:41:17.536
2025-07-02 06:41:17.536         # pump out diffs from after the synch point
2025-07-02 06:41:17.536 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.536
2025-07-02 06:41:17.537 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.537 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.537
2025-07-02 06:41:17.537 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.537 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.537 alo = 247, ahi = 1101
2025-07-02 06:41:17.537 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.537 blo = 247, bhi = 1101
2025-07-02 06:41:17.537
2025-07-02 06:41:17.537     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.537         g = []
2025-07-02 06:41:17.537         if alo < ahi:
2025-07-02 06:41:17.537             if blo < bhi:
2025-07-02 06:41:17.537                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.537             else:
2025-07-02 06:41:17.537                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.537         elif blo < bhi:
2025-07-02 06:41:17.538             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.538
2025-07-02 06:41:17.538 >       yield from g
2025-07-02 06:41:17.538
2025-07-02 06:41:17.538 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.538 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.538
2025-07-02 06:41:17.538 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.538 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.538 alo = 247, ahi = 1101
2025-07-02 06:41:17.538 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.538 blo = 247, bhi = 1101
2025-07-02 06:41:17.538
2025-07-02 06:41:17.538     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.538         r"""
2025-07-02 06:41:17.538         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.538         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.538         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.538         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.539
2025-07-02 06:41:17.539         Example:
2025-07-02 06:41:17.539
2025-07-02 06:41:17.539         >>> d = Differ()
2025-07-02 06:41:17.539         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.539         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.539         >>> print(''.join(results), end="")
2025-07-02 06:41:17.539         - abcDefghiJkl
2025-07-02 06:41:17.539         + abcdefGhijkl
2025-07-02 06:41:17.539         """
2025-07-02 06:41:17.539
2025-07-02 06:41:17.539         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.539         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.539         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.539         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.539         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.539
2025-07-02 06:41:17.539         # search for the pair that matches best without being identical
2025-07-02 06:41:17.540         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.540         # on junk -- unless we have to)
2025-07-02 06:41:17.540         for j in range(blo, bhi):
2025-07-02 06:41:17.540             bj = b[j]
2025-07-02 06:41:17.540             cruncher.set_seq2(bj)
2025-07-02 06:41:17.540             for i in range(alo, ahi):
2025-07-02 06:41:17.540                 ai = a[i]
2025-07-02 06:41:17.540                 if ai == bj:
2025-07-02 06:41:17.540                     if eqi is None:
2025-07-02 06:41:17.540                         eqi, eqj = i, j
2025-07-02 06:41:17.540                     continue
2025-07-02 06:41:17.540                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.540                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.540                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.540                 # compares by a factor of 3.
2025-07-02 06:41:17.540                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.540                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.540                 # of the computation is cached by cruncher
2025-07-02 06:41:17.540                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.541                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.541                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.541                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.541         if best_ratio < cutoff:
2025-07-02 06:41:17.541             # no non-identical "pretty close" pair
2025-07-02 06:41:17.541             if eqi is None:
2025-07-02 06:41:17.541                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.541                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.541                 return
2025-07-02 06:41:17.541             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.541             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.541         else:
2025-07-02 06:41:17.541             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.541             eqi = None
2025-07-02 06:41:17.541
2025-07-02 06:41:17.541         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.541         # identical
2025-07-02 06:41:17.541
2025-07-02 06:41:17.542         # pump out diffs from before the synch point
2025-07-02 06:41:17.542         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.542
2025-07-02 06:41:17.542         # do intraline marking on the synch pair
2025-07-02 06:41:17.542         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.542         if eqi is None:
2025-07-02 06:41:17.542             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.542             atags = btags = ""
2025-07-02 06:41:17.542             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.542             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.542                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.542                 if tag == 'replace':
2025-07-02 06:41:17.542                     atags += '^' * la
2025-07-02 06:41:17.542                     btags += '^' * lb
2025-07-02 06:41:17.542                 elif tag == 'delete':
2025-07-02 06:41:17.542                     atags += '-' * la
2025-07-02 06:41:17.542                 elif tag == 'insert':
2025-07-02 06:41:17.542                     btags += '+' * lb
2025-07-02 06:41:17.542                 elif tag == 'equal':
2025-07-02 06:41:17.543                     atags += ' ' * la
2025-07-02 06:41:17.543                     btags += ' ' * lb
2025-07-02 06:41:17.543                 else:
2025-07-02 06:41:17.543                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.543             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.543         else:
2025-07-02 06:41:17.543             # the synch pair is identical
2025-07-02 06:41:17.543             yield '  ' + aelt
2025-07-02 06:41:17.543
2025-07-02 06:41:17.543         # pump out diffs from after the synch point
2025-07-02 06:41:17.543 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.543
2025-07-02 06:41:17.543 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.543 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.543
2025-07-02 06:41:17.543 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.543 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.543 alo = 248, ahi = 1101
2025-07-02 06:41:17.543 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.544 blo = 248, bhi = 1101
2025-07-02 06:41:17.544
2025-07-02 06:41:17.544     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.544         g = []
2025-07-02 06:41:17.544         if alo < ahi:
2025-07-02 06:41:17.544             if blo < bhi:
2025-07-02 06:41:17.544                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.544             else:
2025-07-02 06:41:17.544                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.544         elif blo < bhi:
2025-07-02 06:41:17.544             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.544
2025-07-02 06:41:17.544 >       yield from g
2025-07-02 06:41:17.544
2025-07-02 06:41:17.544 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.544 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.544
2025-07-02 06:41:17.544 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.544 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.544 alo = 248, ahi = 1101
2025-07-02 06:41:17.545 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.545 blo = 248, bhi = 1101
2025-07-02 06:41:17.545
2025-07-02 06:41:17.545     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.545         r"""
2025-07-02 06:41:17.545         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.545         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.545         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.545         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.545
2025-07-02 06:41:17.545         Example:
2025-07-02 06:41:17.545
2025-07-02 06:41:17.545         >>> d = Differ()
2025-07-02 06:41:17.545         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.545         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.545         >>> print(''.join(results), end="")
2025-07-02 06:41:17.545         - abcDefghiJkl
2025-07-02 06:41:17.545         + abcdefGhijkl
2025-07-02 06:41:17.546         """
2025-07-02 06:41:17.546
2025-07-02 06:41:17.546         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.546         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.546         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.546         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.546         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.546
2025-07-02 06:41:17.546         # search for the pair that matches best without being identical
2025-07-02 06:41:17.546         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.546         # on junk -- unless we have to)
2025-07-02 06:41:17.546         for j in range(blo, bhi):
2025-07-02 06:41:17.546             bj = b[j]
2025-07-02 06:41:17.546             cruncher.set_seq2(bj)
2025-07-02 06:41:17.546             for i in range(alo, ahi):
2025-07-02 06:41:17.546                 ai = a[i]
2025-07-02 06:41:17.546                 if ai == bj:
2025-07-02 06:41:17.546                     if eqi is None:
2025-07-02 06:41:17.546                         eqi, eqj = i, j
2025-07-02 06:41:17.547                     continue
2025-07-02 06:41:17.547                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.547                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.547                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.547                 # compares by a factor of 3.
2025-07-02 06:41:17.547                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.547                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.547                 # of the computation is cached by cruncher
2025-07-02 06:41:17.547                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.547                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.547                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.547                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.547         if best_ratio < cutoff:
2025-07-02 06:41:17.547             # no non-identical "pretty close" pair
2025-07-02 06:41:17.547             if eqi is None:
2025-07-02 06:41:17.547                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.547                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.547                 return
2025-07-02 06:41:17.547             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.547             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.548         else:
2025-07-02 06:41:17.548             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.548             eqi = None
2025-07-02 06:41:17.548
2025-07-02 06:41:17.548         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.548         # identical
2025-07-02 06:41:17.548
2025-07-02 06:41:17.548         # pump out diffs from before the synch point
2025-07-02 06:41:17.548         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.548
2025-07-02 06:41:17.548         # do intraline marking on the synch pair
2025-07-02 06:41:17.548         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.548         if eqi is None:
2025-07-02 06:41:17.548             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.548             atags = btags = ""
2025-07-02 06:41:17.548             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.548             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.548                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.548                 if tag == 'replace':
2025-07-02 06:41:17.549                     atags += '^' * la
2025-07-02 06:41:17.549                     btags += '^' * lb
2025-07-02 06:41:17.549                 elif tag == 'delete':
2025-07-02 06:41:17.549                     atags += '-' * la
2025-07-02 06:41:17.549                 elif tag == 'insert':
2025-07-02 06:41:17.549                     btags += '+' * lb
2025-07-02 06:41:17.549                 elif tag == 'equal':
2025-07-02 06:41:17.549                     atags += ' ' * la
2025-07-02 06:41:17.549                     btags += ' ' * lb
2025-07-02 06:41:17.549                 else:
2025-07-02 06:41:17.549                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.549             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.549         else:
2025-07-02 06:41:17.549             # the synch pair is identical
2025-07-02 06:41:17.549             yield '  ' + aelt
2025-07-02 06:41:17.549
2025-07-02 06:41:17.549         # pump out diffs from after the synch point
2025-07-02 06:41:17.549 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.549
2025-07-02 06:41:17.550 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.550 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.550
2025-07-02 06:41:17.550 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.550 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.550 alo = 249, ahi = 1101
2025-07-02 06:41:17.550 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.550 blo = 249, bhi = 1101
2025-07-02 06:41:17.550
2025-07-02 06:41:17.550     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.550         g = []
2025-07-02 06:41:17.550         if alo < ahi:
2025-07-02 06:41:17.550             if blo < bhi:
2025-07-02 06:41:17.550                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.550             else:
2025-07-02 06:41:17.550                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.550         elif blo < bhi:
2025-07-02 06:41:17.550             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.550
2025-07-02 06:41:17.551 >       yield from g
2025-07-02 06:41:17.551
2025-07-02 06:41:17.551 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.551 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.551
2025-07-02 06:41:17.551 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.551 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.551 alo = 249, ahi = 1101
2025-07-02 06:41:17.551 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.551 blo = 249, bhi = 1101
2025-07-02 06:41:17.551
2025-07-02 06:41:17.551     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.551         r"""
2025-07-02 06:41:17.551         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.551         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.551         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.551         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.551
2025-07-02 06:41:17.551         Example:
2025-07-02 06:41:17.552
2025-07-02 06:41:17.552         >>> d = Differ()
2025-07-02 06:41:17.552         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.552         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.552         >>> print(''.join(results), end="")
2025-07-02 06:41:17.552         - abcDefghiJkl
2025-07-02 06:41:17.552         + abcdefGhijkl
2025-07-02 06:41:17.552         """
2025-07-02 06:41:17.552
2025-07-02 06:41:17.552         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.552         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.552         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.552         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.552         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.552
2025-07-02 06:41:17.552         # search for the pair that matches best without being identical
2025-07-02 06:41:17.552         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.553         # on junk -- unless we have to)
2025-07-02 06:41:17.553         for j in range(blo, bhi):
2025-07-02 06:41:17.553             bj = b[j]
2025-07-02 06:41:17.553             cruncher.set_seq2(bj)
2025-07-02 06:41:17.553             for i in range(alo, ahi):
2025-07-02 06:41:17.553                 ai = a[i]
2025-07-02 06:41:17.553                 if ai == bj:
2025-07-02 06:41:17.553                     if eqi is None:
2025-07-02 06:41:17.553                         eqi, eqj = i, j
2025-07-02 06:41:17.553                     continue
2025-07-02 06:41:17.553                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.553                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.553                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.553                 # compares by a factor of 3.
2025-07-02 06:41:17.553                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.553                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.553                 # of the computation is cached by cruncher
2025-07-02 06:41:17.553                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.554                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.554                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.554                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.554         if best_ratio < cutoff:
2025-07-02 06:41:17.554             # no non-identical "pretty close" pair
2025-07-02 06:41:17.554             if eqi is None:
2025-07-02 06:41:17.554                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.554                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.554                 return
2025-07-02 06:41:17.554             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.554             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.554         else:
2025-07-02 06:41:17.554             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.554             eqi = None
2025-07-02 06:41:17.554
2025-07-02 06:41:17.554         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.554         # identical
2025-07-02 06:41:17.554
2025-07-02 06:41:17.555         # pump out diffs from before the synch point
2025-07-02 06:41:17.555         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.555
2025-07-02 06:41:17.555         # do intraline marking on the synch pair
2025-07-02 06:41:17.555         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.555         if eqi is None:
2025-07-02 06:41:17.555             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.555             atags = btags = ""
2025-07-02 06:41:17.555             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.555             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.555                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.555                 if tag == 'replace':
2025-07-02 06:41:17.555                     atags += '^' * la
2025-07-02 06:41:17.555                     btags += '^' * lb
2025-07-02 06:41:17.555                 elif tag == 'delete':
2025-07-02 06:41:17.555                     atags += '-' * la
2025-07-02 06:41:17.555                 elif tag == 'insert':
2025-07-02 06:41:17.555                     btags += '+' * lb
2025-07-02 06:41:17.555                 elif tag == 'equal':
2025-07-02 06:41:17.555                     atags += ' ' * la
2025-07-02 06:41:17.556                     btags += ' ' * lb
2025-07-02 06:41:17.556                 else:
2025-07-02 06:41:17.556                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.556             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.556         else:
2025-07-02 06:41:17.556             # the synch pair is identical
2025-07-02 06:41:17.556             yield '  ' + aelt
2025-07-02 06:41:17.556
2025-07-02 06:41:17.556         # pump out diffs from after the synch point
2025-07-02 06:41:17.556 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.556
2025-07-02 06:41:17.556 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.556 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.556
2025-07-02 06:41:17.556 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.556 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.556 alo = 250, ahi = 1101
2025-07-02 06:41:17.556 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.556 blo = 250, bhi = 1101
2025-07-02 06:41:17.557
2025-07-02 06:41:17.557     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.557         g = []
2025-07-02 06:41:17.557         if alo < ahi:
2025-07-02 06:41:17.557             if blo < bhi:
2025-07-02 06:41:17.557                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.557             else:
2025-07-02 06:41:17.557                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.557         elif blo < bhi:
2025-07-02 06:41:17.557             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.557
2025-07-02 06:41:17.557 >       yield from g
2025-07-02 06:41:17.557
2025-07-02 06:41:17.557 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.557 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.557
2025-07-02 06:41:17.557 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.557 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.557 alo = 250, ahi = 1101
2025-07-02 06:41:17.558 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.558 blo = 250, bhi = 1101
2025-07-02 06:41:17.558
2025-07-02 06:41:17.558     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.558         r"""
2025-07-02 06:41:17.558         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.558         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.558         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.558         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.558
2025-07-02 06:41:17.558         Example:
2025-07-02 06:41:17.558
2025-07-02 06:41:17.558         >>> d = Differ()
2025-07-02 06:41:17.558         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.558         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.558         >>> print(''.join(results), end="")
2025-07-02 06:41:17.558         - abcDefghiJkl
2025-07-02 06:41:17.558         + abcdefGhijkl
2025-07-02 06:41:17.559         """
2025-07-02 06:41:17.559
2025-07-02 06:41:17.559         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.559         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.559         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.559         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.559         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.559
2025-07-02 06:41:17.559         # search for the pair that matches best without being identical
2025-07-02 06:41:17.559         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.559         # on junk -- unless we have to)
2025-07-02 06:41:17.559         for j in range(blo, bhi):
2025-07-02 06:41:17.559             bj = b[j]
2025-07-02 06:41:17.559             cruncher.set_seq2(bj)
2025-07-02 06:41:17.559             for i in range(alo, ahi):
2025-07-02 06:41:17.559                 ai = a[i]
2025-07-02 06:41:17.559                 if ai == bj:
2025-07-02 06:41:17.559                     if eqi is None:
2025-07-02 06:41:17.560                         eqi, eqj = i, j
2025-07-02 06:41:17.560                     continue
2025-07-02 06:41:17.560                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.560                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.560                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.560                 # compares by a factor of 3.
2025-07-02 06:41:17.560                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.560                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.560                 # of the computation is cached by cruncher
2025-07-02 06:41:17.560                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.560                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.560                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.560                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.560         if best_ratio < cutoff:
2025-07-02 06:41:17.560             # no non-identical "pretty close" pair
2025-07-02 06:41:17.560             if eqi is None:
2025-07-02 06:41:17.560                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.560                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.561                 return
2025-07-02 06:41:17.561             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.561             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.561         else:
2025-07-02 06:41:17.561             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.561             eqi = None
2025-07-02 06:41:17.561
2025-07-02 06:41:17.561         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.561         # identical
2025-07-02 06:41:17.561
2025-07-02 06:41:17.561         # pump out diffs from before the synch point
2025-07-02 06:41:17.561         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.561
2025-07-02 06:41:17.561         # do intraline marking on the synch pair
2025-07-02 06:41:17.561         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.561         if eqi is None:
2025-07-02 06:41:17.561             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.561             atags = btags = ""
2025-07-02 06:41:17.561             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.561             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.562                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.562                 if tag == 'replace':
2025-07-02 06:41:17.562                     atags += '^' * la
2025-07-02 06:41:17.562                     btags += '^' * lb
2025-07-02 06:41:17.562                 elif tag == 'delete':
2025-07-02 06:41:17.562                     atags += '-' * la
2025-07-02 06:41:17.562                 elif tag == 'insert':
2025-07-02 06:41:17.562                     btags += '+' * lb
2025-07-02 06:41:17.562                 elif tag == 'equal':
2025-07-02 06:41:17.562                     atags += ' ' * la
2025-07-02 06:41:17.562                     btags += ' ' * lb
2025-07-02 06:41:17.562                 else:
2025-07-02 06:41:17.562                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.562             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.562         else:
2025-07-02 06:41:17.562             # the synch pair is identical
2025-07-02 06:41:17.562             yield '  ' + aelt
2025-07-02 06:41:17.562
2025-07-02 06:41:17.562         # pump out diffs from after the synch point
2025-07-02 06:41:17.563 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.563
2025-07-02 06:41:17.563 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.563 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.563
2025-07-02 06:41:17.563 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.563 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.563 alo = 251, ahi = 1101
2025-07-02 06:41:17.563 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.563 blo = 251, bhi = 1101
2025-07-02 06:41:17.563
2025-07-02 06:41:17.563     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.563         g = []
2025-07-02 06:41:17.563         if alo < ahi:
2025-07-02 06:41:17.563             if blo < bhi:
2025-07-02 06:41:17.563                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.563             else:
2025-07-02 06:41:17.563                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.563         elif blo < bhi:
2025-07-02 06:41:17.564             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.564
2025-07-02 06:41:17.564 >       yield from g
2025-07-02 06:41:17.564
2025-07-02 06:41:17.564 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.564 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.564
2025-07-02 06:41:17.564 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.564 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.564 alo = 251, ahi = 1101
2025-07-02 06:41:17.564 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.564 blo = 251, bhi = 1101
2025-07-02 06:41:17.564
2025-07-02 06:41:17.564     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.564         r"""
2025-07-02 06:41:17.564         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.564         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.564         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.564         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.564
2025-07-02 06:41:17.565         Example:
2025-07-02 06:41:17.565
2025-07-02 06:41:17.565         >>> d = Differ()
2025-07-02 06:41:17.565         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.565         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.565         >>> print(''.join(results), end="")
2025-07-02 06:41:17.565         - abcDefghiJkl
2025-07-02 06:41:17.565         + abcdefGhijkl
2025-07-02 06:41:17.565         """
2025-07-02 06:41:17.565
2025-07-02 06:41:17.565         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.565         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.565         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.565         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.565         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.565
2025-07-02 06:41:17.565         # search for the pair that matches best without being identical
2025-07-02 06:41:17.565         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.566         # on junk -- unless we have to)
2025-07-02 06:41:17.566         for j in range(blo, bhi):
2025-07-02 06:41:17.566             bj = b[j]
2025-07-02 06:41:17.566             cruncher.set_seq2(bj)
2025-07-02 06:41:17.566             for i in range(alo, ahi):
2025-07-02 06:41:17.566                 ai = a[i]
2025-07-02 06:41:17.566                 if ai == bj:
2025-07-02 06:41:17.566                     if eqi is None:
2025-07-02 06:41:17.566                         eqi, eqj = i, j
2025-07-02 06:41:17.566                     continue
2025-07-02 06:41:17.566                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.566                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.566                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.566                 # compares by a factor of 3.
2025-07-02 06:41:17.566                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.566                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.566                 # of the computation is cached by cruncher
2025-07-02 06:41:17.566                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.566                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.567                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.567                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.567         if best_ratio < cutoff:
2025-07-02 06:41:17.567             # no non-identical "pretty close" pair
2025-07-02 06:41:17.567             if eqi is None:
2025-07-02 06:41:17.567                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.567                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.567                 return
2025-07-02 06:41:17.567             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.567             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.567         else:
2025-07-02 06:41:17.567             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.567             eqi = None
2025-07-02 06:41:17.567
2025-07-02 06:41:17.567         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.567         # identical
2025-07-02 06:41:17.567
2025-07-02 06:41:17.567         # pump out diffs from before the synch point
2025-07-02 06:41:17.567         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.568
2025-07-02 06:41:17.568         # do intraline marking on the synch pair
2025-07-02 06:41:17.568         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.568         if eqi is None:
2025-07-02 06:41:17.568             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.568             atags = btags = ""
2025-07-02 06:41:17.568             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.568             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.568                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.568                 if tag == 'replace':
2025-07-02 06:41:17.568                     atags += '^' * la
2025-07-02 06:41:17.568                     btags += '^' * lb
2025-07-02 06:41:17.568                 elif tag == 'delete':
2025-07-02 06:41:17.568                     atags += '-' * la
2025-07-02 06:41:17.568                 elif tag == 'insert':
2025-07-02 06:41:17.568                     btags += '+' * lb
2025-07-02 06:41:17.568                 elif tag == 'equal':
2025-07-02 06:41:17.568                     atags += ' ' * la
2025-07-02 06:41:17.569                     btags += ' ' * lb
2025-07-02 06:41:17.569                 else:
2025-07-02 06:41:17.569                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.569             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.569         else:
2025-07-02 06:41:17.569             # the synch pair is identical
2025-07-02 06:41:17.569             yield '  ' + aelt
2025-07-02 06:41:17.569
2025-07-02 06:41:17.569         # pump out diffs from after the synch point
2025-07-02 06:41:17.569 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.569
2025-07-02 06:41:17.569 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.569 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.569
2025-07-02 06:41:17.569 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.569 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.569 alo = 252, ahi = 1101
2025-07-02 06:41:17.569 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.569 blo = 252, bhi = 1101
2025-07-02 06:41:17.570
2025-07-02 06:41:17.570     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.570         g = []
2025-07-02 06:41:17.570         if alo < ahi:
2025-07-02 06:41:17.570             if blo < bhi:
2025-07-02 06:41:17.570                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.570             else:
2025-07-02 06:41:17.570                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.570         elif blo < bhi:
2025-07-02 06:41:17.570             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.570
2025-07-02 06:41:17.570 >       yield from g
2025-07-02 06:41:17.570
2025-07-02 06:41:17.570 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.570 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.570
2025-07-02 06:41:17.570 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.570 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.570 alo = 252, ahi = 1101
2025-07-02 06:41:17.570 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.571 blo = 252, bhi = 1101
2025-07-02 06:41:17.571
2025-07-02 06:41:17.571     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.571         r"""
2025-07-02 06:41:17.571         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.571         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.571         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.571         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.571
2025-07-02 06:41:17.571         Example:
2025-07-02 06:41:17.571
2025-07-02 06:41:17.571         >>> d = Differ()
2025-07-02 06:41:17.571         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.571         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.571         >>> print(''.join(results), end="")
2025-07-02 06:41:17.571         - abcDefghiJkl
2025-07-02 06:41:17.571         + abcdefGhijkl
2025-07-02 06:41:17.572         """
2025-07-02 06:41:17.572
2025-07-02 06:41:17.572         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.572         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.572         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.572         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.572         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.572
2025-07-02 06:41:17.572         # search for the pair that matches best without being identical
2025-07-02 06:41:17.572         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.572         # on junk -- unless we have to)
2025-07-02 06:41:17.572         for j in range(blo, bhi):
2025-07-02 06:41:17.572             bj = b[j]
2025-07-02 06:41:17.572             cruncher.set_seq2(bj)
2025-07-02 06:41:17.572             for i in range(alo, ahi):
2025-07-02 06:41:17.572                 ai = a[i]
2025-07-02 06:41:17.572                 if ai == bj:
2025-07-02 06:41:17.572                     if eqi is None:
2025-07-02 06:41:17.572                         eqi, eqj = i, j
2025-07-02 06:41:17.572                     continue
2025-07-02 06:41:17.573                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.573                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.573                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.573                 # compares by a factor of 3.
2025-07-02 06:41:17.573                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.573                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.573                 # of the computation is cached by cruncher
2025-07-02 06:41:17.573                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.573                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.573                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.573                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.573         if best_ratio < cutoff:
2025-07-02 06:41:17.573             # no non-identical "pretty close" pair
2025-07-02 06:41:17.573             if eqi is None:
2025-07-02 06:41:17.573                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.573                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.573                 return
2025-07-02 06:41:17.573             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.573             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.574         else:
2025-07-02 06:41:17.574             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.574             eqi = None
2025-07-02 06:41:17.574
2025-07-02 06:41:17.574         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.574         # identical
2025-07-02 06:41:17.574
2025-07-02 06:41:17.574         # pump out diffs from before the synch point
2025-07-02 06:41:17.574         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.574
2025-07-02 06:41:17.574         # do intraline marking on the synch pair
2025-07-02 06:41:17.574         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.574         if eqi is None:
2025-07-02 06:41:17.574             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.574             atags = btags = ""
2025-07-02 06:41:17.574             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.574             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.574                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.574                 if tag == 'replace':
2025-07-02 06:41:17.574                     atags += '^' * la
2025-07-02 06:41:17.575                     btags += '^' * lb
2025-07-02 06:41:17.575                 elif tag == 'delete':
2025-07-02 06:41:17.575                     atags += '-' * la
2025-07-02 06:41:17.575                 elif tag == 'insert':
2025-07-02 06:41:17.575                     btags += '+' * lb
2025-07-02 06:41:17.575                 elif tag == 'equal':
2025-07-02 06:41:17.575                     atags += ' ' * la
2025-07-02 06:41:17.575                     btags += ' ' * lb
2025-07-02 06:41:17.575                 else:
2025-07-02 06:41:17.575                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.575             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.575         else:
2025-07-02 06:41:17.575             # the synch pair is identical
2025-07-02 06:41:17.575             yield '  ' + aelt
2025-07-02 06:41:17.575
2025-07-02 06:41:17.575         # pump out diffs from after the synch point
2025-07-02 06:41:17.575 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.575
2025-07-02 06:41:17.575 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.576 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.576
2025-07-02 06:41:17.576 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.576 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.576 alo = 253, ahi = 1101
2025-07-02 06:41:17.576 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.576 blo = 253, bhi = 1101
2025-07-02 06:41:17.576
2025-07-02 06:41:17.576     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.576         g = []
2025-07-02 06:41:17.576         if alo < ahi:
2025-07-02 06:41:17.576             if blo < bhi:
2025-07-02 06:41:17.576                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.576             else:
2025-07-02 06:41:17.576                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.576         elif blo < bhi:
2025-07-02 06:41:17.576             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.576
2025-07-02 06:41:17.576 >       yield from g
2025-07-02 06:41:17.577
2025-07-02 06:41:17.577 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.577 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.577
2025-07-02 06:41:17.577 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.577 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.577 alo = 253, ahi = 1101
2025-07-02 06:41:17.577 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.577 blo = 253, bhi = 1101
2025-07-02 06:41:17.577
2025-07-02 06:41:17.577     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.577         r"""
2025-07-02 06:41:17.577         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.577         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.577         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.577         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.577
2025-07-02 06:41:17.577         Example:
2025-07-02 06:41:17.578
2025-07-02 06:41:17.578         >>> d = Differ()
2025-07-02 06:41:17.578         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.578         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.578         >>> print(''.join(results), end="")
2025-07-02 06:41:17.578         - abcDefghiJkl
2025-07-02 06:41:17.578         + abcdefGhijkl
2025-07-02 06:41:17.578         """
2025-07-02 06:41:17.578
2025-07-02 06:41:17.578         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.578         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.578         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.578         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.578         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.578
2025-07-02 06:41:17.578         # search for the pair that matches best without being identical
2025-07-02 06:41:17.578         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.578         # on junk -- unless we have to)
2025-07-02 06:41:17.579         for j in range(blo, bhi):
2025-07-02 06:41:17.579             bj = b[j]
2025-07-02 06:41:17.579             cruncher.set_seq2(bj)
2025-07-02 06:41:17.579             for i in range(alo, ahi):
2025-07-02 06:41:17.579                 ai = a[i]
2025-07-02 06:41:17.579                 if ai == bj:
2025-07-02 06:41:17.579                     if eqi is None:
2025-07-02 06:41:17.579                         eqi, eqj = i, j
2025-07-02 06:41:17.579                     continue
2025-07-02 06:41:17.579                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.579                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.579                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.579                 # compares by a factor of 3.
2025-07-02 06:41:17.579                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.579                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.579                 # of the computation is cached by cruncher
2025-07-02 06:41:17.579                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.579                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.579                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.580                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.580         if best_ratio < cutoff:
2025-07-02 06:41:17.580             # no non-identical "pretty close" pair
2025-07-02 06:41:17.580             if eqi is None:
2025-07-02 06:41:17.580                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.580                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.580                 return
2025-07-02 06:41:17.580             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.580             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.580         else:
2025-07-02 06:41:17.580             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.580             eqi = None
2025-07-02 06:41:17.580
2025-07-02 06:41:17.580         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.580         # identical
2025-07-02 06:41:17.580
2025-07-02 06:41:17.580         # pump out diffs from before the synch point
2025-07-02 06:41:17.580         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.580
2025-07-02 06:41:17.580         # do intraline marking on the synch pair
2025-07-02 06:41:17.581         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.581         if eqi is None:
2025-07-02 06:41:17.581             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.581             atags = btags = ""
2025-07-02 06:41:17.581             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.581             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.581                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.581                 if tag == 'replace':
2025-07-02 06:41:17.581                     atags += '^' * la
2025-07-02 06:41:17.581                     btags += '^' * lb
2025-07-02 06:41:17.581                 elif tag == 'delete':
2025-07-02 06:41:17.581                     atags += '-' * la
2025-07-02 06:41:17.581                 elif tag == 'insert':
2025-07-02 06:41:17.581                     btags += '+' * lb
2025-07-02 06:41:17.581                 elif tag == 'equal':
2025-07-02 06:41:17.581                     atags += ' ' * la
2025-07-02 06:41:17.581                     btags += ' ' * lb
2025-07-02 06:41:17.581                 else:
2025-07-02 06:41:17.581                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.582             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.582         else:
2025-07-02 06:41:17.582             # the synch pair is identical
2025-07-02 06:41:17.582             yield '  ' + aelt
2025-07-02 06:41:17.582
2025-07-02 06:41:17.582         # pump out diffs from after the synch point
2025-07-02 06:41:17.582 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.582
2025-07-02 06:41:17.582 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.582 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.582
2025-07-02 06:41:17.582 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.582 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.582 alo = 254, ahi = 1101
2025-07-02 06:41:17.582 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.582 blo = 254, bhi = 1101
2025-07-02 06:41:17.582
2025-07-02 06:41:17.582     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.582         g = []
2025-07-02 06:41:17.582         if alo < ahi:
2025-07-02 06:41:17.583             if blo < bhi:
2025-07-02 06:41:17.583                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.583             else:
2025-07-02 06:41:17.583                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.583         elif blo < bhi:
2025-07-02 06:41:17.583             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.583
2025-07-02 06:41:17.583 >       yield from g
2025-07-02 06:41:17.583
2025-07-02 06:41:17.583 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.583 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.583
2025-07-02 06:41:17.583 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.583 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.583 alo = 254, ahi = 1101
2025-07-02 06:41:17.583 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.583 blo = 254, bhi = 1101
2025-07-02 06:41:17.583
2025-07-02 06:41:17.584     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.584         r"""
2025-07-02 06:41:17.584         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.584         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.584         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.584         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.584
2025-07-02 06:41:17.584         Example:
2025-07-02 06:41:17.584
2025-07-02 06:41:17.584         >>> d = Differ()
2025-07-02 06:41:17.584         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.584         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.584         >>> print(''.join(results), end="")
2025-07-02 06:41:17.584         - abcDefghiJkl
2025-07-02 06:41:17.584         + abcdefGhijkl
2025-07-02 06:41:17.584         """
2025-07-02 06:41:17.584
2025-07-02 06:41:17.585         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.585         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.585         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.585         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.585         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.585
2025-07-02 06:41:17.585         # search for the pair that matches best without being identical
2025-07-02 06:41:17.585         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.585         # on junk -- unless we have to)
2025-07-02 06:41:17.585         for j in range(blo, bhi):
2025-07-02 06:41:17.585             bj = b[j]
2025-07-02 06:41:17.585             cruncher.set_seq2(bj)
2025-07-02 06:41:17.585             for i in range(alo, ahi):
2025-07-02 06:41:17.585                 ai = a[i]
2025-07-02 06:41:17.585                 if ai == bj:
2025-07-02 06:41:17.585                     if eqi is None:
2025-07-02 06:41:17.585                         eqi, eqj = i, j
2025-07-02 06:41:17.585                     continue
2025-07-02 06:41:17.585                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.586                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.586                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.586                 # compares by a factor of 3.
2025-07-02 06:41:17.586                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.586                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.586                 # of the computation is cached by cruncher
2025-07-02 06:41:17.586                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.586                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.586                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.586                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.586         if best_ratio < cutoff:
2025-07-02 06:41:17.586             # no non-identical "pretty close" pair
2025-07-02 06:41:17.586             if eqi is None:
2025-07-02 06:41:17.586                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.586                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.586                 return
2025-07-02 06:41:17.586             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.586             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.586         else:
2025-07-02 06:41:17.587             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.587             eqi = None
2025-07-02 06:41:17.587
2025-07-02 06:41:17.587         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.587         # identical
2025-07-02 06:41:17.587
2025-07-02 06:41:17.587         # pump out diffs from before the synch point
2025-07-02 06:41:17.587         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.587
2025-07-02 06:41:17.587         # do intraline marking on the synch pair
2025-07-02 06:41:17.587         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.587         if eqi is None:
2025-07-02 06:41:17.587             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.587             atags = btags = ""
2025-07-02 06:41:17.587             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.587             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.587                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.587                 if tag == 'replace':
2025-07-02 06:41:17.587                     atags += '^' * la
2025-07-02 06:41:17.588                     btags += '^' * lb
2025-07-02 06:41:17.588                 elif tag == 'delete':
2025-07-02 06:41:17.588                     atags += '-' * la
2025-07-02 06:41:17.588                 elif tag == 'insert':
2025-07-02 06:41:17.588                     btags += '+' * lb
2025-07-02 06:41:17.588                 elif tag == 'equal':
2025-07-02 06:41:17.588                     atags += ' ' * la
2025-07-02 06:41:17.588                     btags += ' ' * lb
2025-07-02 06:41:17.588                 else:
2025-07-02 06:41:17.588                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.588             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.588         else:
2025-07-02 06:41:17.588             # the synch pair is identical
2025-07-02 06:41:17.588             yield '  ' + aelt
2025-07-02 06:41:17.588
2025-07-02 06:41:17.588         # pump out diffs from after the synch point
2025-07-02 06:41:17.588 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.588
2025-07-02 06:41:17.588 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.588 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.589
2025-07-02 06:41:17.589 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.589 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.589 alo = 255, ahi = 1101
2025-07-02 06:41:17.589 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.589 blo = 255, bhi = 1101
2025-07-02 06:41:17.589
2025-07-02 06:41:17.589     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.589         g = []
2025-07-02 06:41:17.589         if alo < ahi:
2025-07-02 06:41:17.589             if blo < bhi:
2025-07-02 06:41:17.589                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.589             else:
2025-07-02 06:41:17.589                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.589         elif blo < bhi:
2025-07-02 06:41:17.589             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.589
2025-07-02 06:41:17.589 >       yield from g
2025-07-02 06:41:17.589
2025-07-02 06:41:17.590 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.590 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.590
2025-07-02 06:41:17.590 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.590 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.590 alo = 255, ahi = 1101
2025-07-02 06:41:17.590 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.590 blo = 255, bhi = 1101
2025-07-02 06:41:17.590
2025-07-02 06:41:17.590     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.590         r"""
2025-07-02 06:41:17.590         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.590         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.590         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.590         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.590
2025-07-02 06:41:17.590         Example:
2025-07-02 06:41:17.590
2025-07-02 06:41:17.590         >>> d = Differ()
2025-07-02 06:41:17.591         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.591         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.591         >>> print(''.join(results), end="")
2025-07-02 06:41:17.591         - abcDefghiJkl
2025-07-02 06:41:17.591         + abcdefGhijkl
2025-07-02 06:41:17.591         """
2025-07-02 06:41:17.591
2025-07-02 06:41:17.591         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.591         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.591         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.591         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.591         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.591
2025-07-02 06:41:17.591         # search for the pair that matches best without being identical
2025-07-02 06:41:17.591         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.591         # on junk -- unless we have to)
2025-07-02 06:41:17.591         for j in range(blo, bhi):
2025-07-02 06:41:17.591             bj = b[j]
2025-07-02 06:41:17.592             cruncher.set_seq2(bj)
2025-07-02 06:41:17.592             for i in range(alo, ahi):
2025-07-02 06:41:17.592                 ai = a[i]
2025-07-02 06:41:17.592                 if ai == bj:
2025-07-02 06:41:17.592                     if eqi is None:
2025-07-02 06:41:17.592                         eqi, eqj = i, j
2025-07-02 06:41:17.592                     continue
2025-07-02 06:41:17.592                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.592                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.592                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.592                 # compares by a factor of 3.
2025-07-02 06:41:17.592                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.592                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.592                 # of the computation is cached by cruncher
2025-07-02 06:41:17.592                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.592                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.592                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.592                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.592         if best_ratio < cutoff:
2025-07-02 06:41:17.593             # no non-identical "pretty close" pair
2025-07-02 06:41:17.593             if eqi is None:
2025-07-02 06:41:17.593                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.593                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.593                 return
2025-07-02 06:41:17.593             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.593             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.593         else:
2025-07-02 06:41:17.593             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.593             eqi = None
2025-07-02 06:41:17.593
2025-07-02 06:41:17.593         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.593         # identical
2025-07-02 06:41:17.593
2025-07-02 06:41:17.593         # pump out diffs from before the synch point
2025-07-02 06:41:17.593         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.593
2025-07-02 06:41:17.593         # do intraline marking on the synch pair
2025-07-02 06:41:17.593         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.593         if eqi is None:
2025-07-02 06:41:17.594             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.594             atags = btags = ""
2025-07-02 06:41:17.594             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.594             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.594                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.594                 if tag == 'replace':
2025-07-02 06:41:17.594                     atags += '^' * la
2025-07-02 06:41:17.594                     btags += '^' * lb
2025-07-02 06:41:17.594                 elif tag == 'delete':
2025-07-02 06:41:17.594                     atags += '-' * la
2025-07-02 06:41:17.594                 elif tag == 'insert':
2025-07-02 06:41:17.594                     btags += '+' * lb
2025-07-02 06:41:17.594                 elif tag == 'equal':
2025-07-02 06:41:17.594                     atags += ' ' * la
2025-07-02 06:41:17.594                     btags += ' ' * lb
2025-07-02 06:41:17.594                 else:
2025-07-02 06:41:17.594                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.594             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.594         else:
2025-07-02 06:41:17.595             # the synch pair is identical
2025-07-02 06:41:17.595             yield '  ' + aelt
2025-07-02 06:41:17.595
2025-07-02 06:41:17.595         # pump out diffs from after the synch point
2025-07-02 06:41:17.595 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.595
2025-07-02 06:41:17.595 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.595 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.595
2025-07-02 06:41:17.595 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.595 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.595 alo = 256, ahi = 1101
2025-07-02 06:41:17.595 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.595 blo = 256, bhi = 1101
2025-07-02 06:41:17.595
2025-07-02 06:41:17.595     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.595         g = []
2025-07-02 06:41:17.595         if alo < ahi:
2025-07-02 06:41:17.596             if blo < bhi:
2025-07-02 06:41:17.596                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.596             else:
2025-07-02 06:41:17.596                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.596         elif blo < bhi:
2025-07-02 06:41:17.596             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.596
2025-07-02 06:41:17.596 >       yield from g
2025-07-02 06:41:17.596
2025-07-02 06:41:17.596 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.596 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.596
2025-07-02 06:41:17.596 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.596 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.596 alo = 256, ahi = 1101
2025-07-02 06:41:17.596 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.596 blo = 256, bhi = 1101
2025-07-02 06:41:17.596
2025-07-02 06:41:17.596     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.597         r"""
2025-07-02 06:41:17.597         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.597         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.597         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.597         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.597
2025-07-02 06:41:17.597         Example:
2025-07-02 06:41:17.597
2025-07-02 06:41:17.597         >>> d = Differ()
2025-07-02 06:41:17.597         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.597         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.597         >>> print(''.join(results), end="")
2025-07-02 06:41:17.597         - abcDefghiJkl
2025-07-02 06:41:17.597         + abcdefGhijkl
2025-07-02 06:41:17.597         """
2025-07-02 06:41:17.597
2025-07-02 06:41:17.597         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.597         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.598         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.598         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.598         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.598
2025-07-02 06:41:17.598         # search for the pair that matches best without being identical
2025-07-02 06:41:17.598         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.598         # on junk -- unless we have to)
2025-07-02 06:41:17.598         for j in range(blo, bhi):
2025-07-02 06:41:17.598             bj = b[j]
2025-07-02 06:41:17.598             cruncher.set_seq2(bj)
2025-07-02 06:41:17.598             for i in range(alo, ahi):
2025-07-02 06:41:17.598                 ai = a[i]
2025-07-02 06:41:17.598                 if ai == bj:
2025-07-02 06:41:17.598                     if eqi is None:
2025-07-02 06:41:17.598                         eqi, eqj = i, j
2025-07-02 06:41:17.598                     continue
2025-07-02 06:41:17.598                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.598                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.598                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.599                 # compares by a factor of 3.
2025-07-02 06:41:17.599                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.599                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.599                 # of the computation is cached by cruncher
2025-07-02 06:41:17.599                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.599                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.599                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.599                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.599         if best_ratio < cutoff:
2025-07-02 06:41:17.599             # no non-identical "pretty close" pair
2025-07-02 06:41:17.599             if eqi is None:
2025-07-02 06:41:17.599                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.599                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.599                 return
2025-07-02 06:41:17.599             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.599             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.599         else:
2025-07-02 06:41:17.599             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.600             eqi = None
2025-07-02 06:41:17.600
2025-07-02 06:41:17.600         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.600         # identical
2025-07-02 06:41:17.600
2025-07-02 06:41:17.600         # pump out diffs from before the synch point
2025-07-02 06:41:17.600         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.600
2025-07-02 06:41:17.600         # do intraline marking on the synch pair
2025-07-02 06:41:17.600         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.600         if eqi is None:
2025-07-02 06:41:17.600             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.600             atags = btags = ""
2025-07-02 06:41:17.600             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.600             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.600                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.600                 if tag == 'replace':
2025-07-02 06:41:17.600                     atags += '^' * la
2025-07-02 06:41:17.601                     btags += '^' * lb
2025-07-02 06:41:17.601                 elif tag == 'delete':
2025-07-02 06:41:17.601                     atags += '-' * la
2025-07-02 06:41:17.601                 elif tag == 'insert':
2025-07-02 06:41:17.601                     btags += '+' * lb
2025-07-02 06:41:17.601                 elif tag == 'equal':
2025-07-02 06:41:17.601                     atags += ' ' * la
2025-07-02 06:41:17.601                     btags += ' ' * lb
2025-07-02 06:41:17.601                 else:
2025-07-02 06:41:17.601                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.601             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.601         else:
2025-07-02 06:41:17.601             # the synch pair is identical
2025-07-02 06:41:17.601             yield '  ' + aelt
2025-07-02 06:41:17.601
2025-07-02 06:41:17.601         # pump out diffs from after the synch point
2025-07-02 06:41:17.601 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.601
2025-07-02 06:41:17.601 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.602 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.602
2025-07-02 06:41:17.602 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.602 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.602 alo = 257, ahi = 1101
2025-07-02 06:41:17.602 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.602 blo = 257, bhi = 1101
2025-07-02 06:41:17.602
2025-07-02 06:41:17.602     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.602         g = []
2025-07-02 06:41:17.602         if alo < ahi:
2025-07-02 06:41:17.602             if blo < bhi:
2025-07-02 06:41:17.602                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.602             else:
2025-07-02 06:41:17.602                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.602         elif blo < bhi:
2025-07-02 06:41:17.602             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.602
2025-07-02 06:41:17.602 >       yield from g
2025-07-02 06:41:17.603
2025-07-02 06:41:17.603 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.603 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.603
2025-07-02 06:41:17.603 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.603 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.603 alo = 257, ahi = 1101
2025-07-02 06:41:17.603 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.603 blo = 257, bhi = 1101
2025-07-02 06:41:17.603
2025-07-02 06:41:17.603     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.603         r"""
2025-07-02 06:41:17.603         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.603         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.603         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.603         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.603
2025-07-02 06:41:17.604         Example:
2025-07-02 06:41:17.604
2025-07-02 06:41:17.604         >>> d = Differ()
2025-07-02 06:41:17.604         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.604         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.604         >>> print(''.join(results), end="")
2025-07-02 06:41:17.604         - abcDefghiJkl
2025-07-02 06:41:17.604         + abcdefGhijkl
2025-07-02 06:41:17.604         """
2025-07-02 06:41:17.604
2025-07-02 06:41:17.604         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.604         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.604         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.604         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.604         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.604
2025-07-02 06:41:17.605         # search for the pair that matches best without being identical
2025-07-02 06:41:17.605         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.605         # on junk -- unless we have to)
2025-07-02 06:41:17.605         for j in range(blo, bhi):
2025-07-02 06:41:17.605             bj = b[j]
2025-07-02 06:41:17.605             cruncher.set_seq2(bj)
2025-07-02 06:41:17.605             for i in range(alo, ahi):
2025-07-02 06:41:17.605                 ai = a[i]
2025-07-02 06:41:17.605                 if ai == bj:
2025-07-02 06:41:17.605                     if eqi is None:
2025-07-02 06:41:17.605                         eqi, eqj = i, j
2025-07-02 06:41:17.605                     continue
2025-07-02 06:41:17.605                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.605                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.605                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.605                 # compares by a factor of 3.
2025-07-02 06:41:17.605                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.605                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.606                 # of the computation is cached by cruncher
2025-07-02 06:41:17.606                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.606                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.606                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.606                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.606         if best_ratio < cutoff:
2025-07-02 06:41:17.606             # no non-identical "pretty close" pair
2025-07-02 06:41:17.606             if eqi is None:
2025-07-02 06:41:17.606                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.606                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.606                 return
2025-07-02 06:41:17.606             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.606             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.606         else:
2025-07-02 06:41:17.606             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.606             eqi = None
2025-07-02 06:41:17.606
2025-07-02 06:41:17.606         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.606         # identical
2025-07-02 06:41:17.607
2025-07-02 06:41:17.607         # pump out diffs from before the synch point
2025-07-02 06:41:17.607         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.607
2025-07-02 06:41:17.607         # do intraline marking on the synch pair
2025-07-02 06:41:17.607         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.607         if eqi is None:
2025-07-02 06:41:17.607             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.607             atags = btags = ""
2025-07-02 06:41:17.607             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.607             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.607                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.607                 if tag == 'replace':
2025-07-02 06:41:17.607                     atags += '^' * la
2025-07-02 06:41:17.607                     btags += '^' * lb
2025-07-02 06:41:17.607                 elif tag == 'delete':
2025-07-02 06:41:17.607                     atags += '-' * la
2025-07-02 06:41:17.607                 elif tag == 'insert':
2025-07-02 06:41:17.607                     btags += '+' * lb
2025-07-02 06:41:17.608                 elif tag == 'equal':
2025-07-02 06:41:17.608                     atags += ' ' * la
2025-07-02 06:41:17.608                     btags += ' ' * lb
2025-07-02 06:41:17.608                 else:
2025-07-02 06:41:17.608                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.608             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.608         else:
2025-07-02 06:41:17.608             # the synch pair is identical
2025-07-02 06:41:17.608             yield '  ' + aelt
2025-07-02 06:41:17.608
2025-07-02 06:41:17.608         # pump out diffs from after the synch point
2025-07-02 06:41:17.608 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.608
2025-07-02 06:41:17.608 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.608 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.608
2025-07-02 06:41:17.608 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.608 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.609 alo = 258, ahi = 1101
2025-07-02 06:41:17.609 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.609 blo = 258, bhi = 1101
2025-07-02 06:41:17.609
2025-07-02 06:41:17.609     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.609         g = []
2025-07-02 06:41:17.609         if alo < ahi:
2025-07-02 06:41:17.609             if blo < bhi:
2025-07-02 06:41:17.609                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.609             else:
2025-07-02 06:41:17.609                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.609         elif blo < bhi:
2025-07-02 06:41:17.609             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.609
2025-07-02 06:41:17.609 >       yield from g
2025-07-02 06:41:17.609
2025-07-02 06:41:17.609 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.609 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.609
2025-07-02 06:41:17.610 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.610 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.610 alo = 258, ahi = 1101
2025-07-02 06:41:17.610 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.610 blo = 258, bhi = 1101
2025-07-02 06:41:17.610
2025-07-02 06:41:17.610     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.610         r"""
2025-07-02 06:41:17.610         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.610         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.610         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.610         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.610
2025-07-02 06:41:17.610         Example:
2025-07-02 06:41:17.610
2025-07-02 06:41:17.610         >>> d = Differ()
2025-07-02 06:41:17.610         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.610         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.611         >>> print(''.join(results), end="")
2025-07-02 06:41:17.611         - abcDefghiJkl
2025-07-02 06:41:17.611         + abcdefGhijkl
2025-07-02 06:41:17.611         """
2025-07-02 06:41:17.611
2025-07-02 06:41:17.611         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.611         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.611         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.611         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.611         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.611
2025-07-02 06:41:17.611         # search for the pair that matches best without being identical
2025-07-02 06:41:17.611         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.611         # on junk -- unless we have to)
2025-07-02 06:41:17.611         for j in range(blo, bhi):
2025-07-02 06:41:17.611             bj = b[j]
2025-07-02 06:41:17.611             cruncher.set_seq2(bj)
2025-07-02 06:41:17.612             for i in range(alo, ahi):
2025-07-02 06:41:17.612                 ai = a[i]
2025-07-02 06:41:17.612                 if ai == bj:
2025-07-02 06:41:17.612                     if eqi is None:
2025-07-02 06:41:17.612                         eqi, eqj = i, j
2025-07-02 06:41:17.612                     continue
2025-07-02 06:41:17.612                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.612                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.612                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.612                 # compares by a factor of 3.
2025-07-02 06:41:17.612                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.612                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.612                 # of the computation is cached by cruncher
2025-07-02 06:41:17.612                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.612                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.612                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.612                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.612         if best_ratio < cutoff:
2025-07-02 06:41:17.612             # no non-identical "pretty close" pair
2025-07-02 06:41:17.613             if eqi is None:
2025-07-02 06:41:17.613                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.613                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.613                 return
2025-07-02 06:41:17.613             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.613             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.613         else:
2025-07-02 06:41:17.613             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.613             eqi = None
2025-07-02 06:41:17.613
2025-07-02 06:41:17.613         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.613         # identical
2025-07-02 06:41:17.613
2025-07-02 06:41:17.613         # pump out diffs from before the synch point
2025-07-02 06:41:17.613         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.613
2025-07-02 06:41:17.613         # do intraline marking on the synch pair
2025-07-02 06:41:17.614         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.614         if eqi is None:
2025-07-02 06:41:17.614             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.614             atags = btags = ""
2025-07-02 06:41:17.614             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.614             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.614                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.614                 if tag == 'replace':
2025-07-02 06:41:17.614                     atags += '^' * la
2025-07-02 06:41:17.614                     btags += '^' * lb
2025-07-02 06:41:17.614                 elif tag == 'delete':
2025-07-02 06:41:17.614                     atags += '-' * la
2025-07-02 06:41:17.614                 elif tag == 'insert':
2025-07-02 06:41:17.614                     btags += '+' * lb
2025-07-02 06:41:17.614                 elif tag == 'equal':
2025-07-02 06:41:17.614                     atags += ' ' * la
2025-07-02 06:41:17.614                     btags += ' ' * lb
2025-07-02 06:41:17.614                 else:
2025-07-02 06:41:17.614                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.614             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.615         else:
2025-07-02 06:41:17.615             # the synch pair is identical
2025-07-02 06:41:17.615             yield '  ' + aelt
2025-07-02 06:41:17.615
2025-07-02 06:41:17.615         # pump out diffs from after the synch point
2025-07-02 06:41:17.615 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.615
2025-07-02 06:41:17.615 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.615 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.615
2025-07-02 06:41:17.615 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.615 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.615 alo = 259, ahi = 1101
2025-07-02 06:41:17.615 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.615 blo = 259, bhi = 1101
2025-07-02 06:41:17.615
2025-07-02 06:41:17.615     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.616         g = []
2025-07-02 06:41:17.616         if alo < ahi:
2025-07-02 06:41:17.616             if blo < bhi:
2025-07-02 06:41:17.616                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.616             else:
2025-07-02 06:41:17.616                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.616         elif blo < bhi:
2025-07-02 06:41:17.616             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.616
2025-07-02 06:41:17.616 >       yield from g
2025-07-02 06:41:17.616
2025-07-02 06:41:17.616 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.616 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.616
2025-07-02 06:41:17.616 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.616 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.616 alo = 259, ahi = 1101
2025-07-02 06:41:17.616 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.616 blo = 259, bhi = 1101
2025-07-02 06:41:17.616
2025-07-02 06:41:17.617     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.617         r"""
2025-07-02 06:41:17.617         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.617         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.617         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.617         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.617
2025-07-02 06:41:17.617         Example:
2025-07-02 06:41:17.617
2025-07-02 06:41:17.617         >>> d = Differ()
2025-07-02 06:41:17.617         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.617         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.617         >>> print(''.join(results), end="")
2025-07-02 06:41:17.617         - abcDefghiJkl
2025-07-02 06:41:17.617         + abcdefGhijkl
2025-07-02 06:41:17.617         """
2025-07-02 06:41:17.617
2025-07-02 06:41:17.617         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.617         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.618         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.618         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.618         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.618
2025-07-02 06:41:17.618         # search for the pair that matches best without being identical
2025-07-02 06:41:17.618         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.618         # on junk -- unless we have to)
2025-07-02 06:41:17.618         for j in range(blo, bhi):
2025-07-02 06:41:17.618             bj = b[j]
2025-07-02 06:41:17.618             cruncher.set_seq2(bj)
2025-07-02 06:41:17.618             for i in range(alo, ahi):
2025-07-02 06:41:17.618                 ai = a[i]
2025-07-02 06:41:17.618                 if ai == bj:
2025-07-02 06:41:17.618                     if eqi is None:
2025-07-02 06:41:17.618                         eqi, eqj = i, j
2025-07-02 06:41:17.618                     continue
2025-07-02 06:41:17.618                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.618                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.618                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.618                 # compares by a factor of 3.
2025-07-02 06:41:17.619                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.619                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.619                 # of the computation is cached by cruncher
2025-07-02 06:41:17.619                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.619                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.619                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.619                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.619         if best_ratio < cutoff:
2025-07-02 06:41:17.619             # no non-identical "pretty close" pair
2025-07-02 06:41:17.619             if eqi is None:
2025-07-02 06:41:17.619                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.619                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.619                 return
2025-07-02 06:41:17.619             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.619             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.619         else:
2025-07-02 06:41:17.619             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.619             eqi = None
2025-07-02 06:41:17.619
2025-07-02 06:41:17.619         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.620         # identical
2025-07-02 06:41:17.620
2025-07-02 06:41:17.620         # pump out diffs from before the synch point
2025-07-02 06:41:17.620         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.620
2025-07-02 06:41:17.620         # do intraline marking on the synch pair
2025-07-02 06:41:17.620         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.620         if eqi is None:
2025-07-02 06:41:17.620             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.620             atags = btags = ""
2025-07-02 06:41:17.620             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.620             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.620                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.620                 if tag == 'replace':
2025-07-02 06:41:17.620                     atags += '^' * la
2025-07-02 06:41:17.620                     btags += '^' * lb
2025-07-02 06:41:17.620                 elif tag == 'delete':
2025-07-02 06:41:17.620                     atags += '-' * la
2025-07-02 06:41:17.620                 elif tag == 'insert':
2025-07-02 06:41:17.620                     btags += '+' * lb
2025-07-02 06:41:17.620                 elif tag == 'equal':
2025-07-02 06:41:17.621                     atags += ' ' * la
2025-07-02 06:41:17.621                     btags += ' ' * lb
2025-07-02 06:41:17.621                 else:
2025-07-02 06:41:17.621                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.621             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.621         else:
2025-07-02 06:41:17.621             # the synch pair is identical
2025-07-02 06:41:17.621             yield '  ' + aelt
2025-07-02 06:41:17.621
2025-07-02 06:41:17.621         # pump out diffs from after the synch point
2025-07-02 06:41:17.621 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.621
2025-07-02 06:41:17.621 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.621 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.621
2025-07-02 06:41:17.621 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.621 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.621 alo = 260, ahi = 1101
2025-07-02 06:41:17.621 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.622 blo = 260, bhi = 1101
2025-07-02 06:41:17.622
2025-07-02 06:41:17.622     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.622         g = []
2025-07-02 06:41:17.622         if alo < ahi:
2025-07-02 06:41:17.622             if blo < bhi:
2025-07-02 06:41:17.622                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.622             else:
2025-07-02 06:41:17.622                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.622         elif blo < bhi:
2025-07-02 06:41:17.622             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.622
2025-07-02 06:41:17.622 >       yield from g
2025-07-02 06:41:17.622
2025-07-02 06:41:17.622 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.622 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.622
2025-07-02 06:41:17.622 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.622 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.623 alo = 260, ahi = 1101
2025-07-02 06:41:17.623 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.623 blo = 260, bhi = 1101
2025-07-02 06:41:17.623
2025-07-02 06:41:17.623     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.623         r"""
2025-07-02 06:41:17.623         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.623         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.623         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.623         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.623
2025-07-02 06:41:17.623         Example:
2025-07-02 06:41:17.623
2025-07-02 06:41:17.623         >>> d = Differ()
2025-07-02 06:41:17.623         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.623         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.623         >>> print(''.join(results), end="")
2025-07-02 06:41:17.623         - abcDefghiJkl
2025-07-02 06:41:17.624         + abcdefGhijkl
2025-07-02 06:41:17.624         """
2025-07-02 06:41:17.624
2025-07-02 06:41:17.624         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.624         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.624         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.624         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.624         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.624
2025-07-02 06:41:17.624         # search for the pair that matches best without being identical
2025-07-02 06:41:17.624         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.624         # on junk -- unless we have to)
2025-07-02 06:41:17.624         for j in range(blo, bhi):
2025-07-02 06:41:17.624             bj = b[j]
2025-07-02 06:41:17.624             cruncher.set_seq2(bj)
2025-07-02 06:41:17.624             for i in range(alo, ahi):
2025-07-02 06:41:17.624                 ai = a[i]
2025-07-02 06:41:17.624                 if ai == bj:
2025-07-02 06:41:17.624                     if eqi is None:
2025-07-02 06:41:17.624                         eqi, eqj = i, j
2025-07-02 06:41:17.625                     continue
2025-07-02 06:41:17.625                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.625                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.625                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.625                 # compares by a factor of 3.
2025-07-02 06:41:17.625                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.625                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.625                 # of the computation is cached by cruncher
2025-07-02 06:41:17.625                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.625                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.625                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.625                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.625         if best_ratio < cutoff:
2025-07-02 06:41:17.625             # no non-identical "pretty close" pair
2025-07-02 06:41:17.625             if eqi is None:
2025-07-02 06:41:17.625                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.625                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.625                 return
2025-07-02 06:41:17.625             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.625             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.626         else:
2025-07-02 06:41:17.626             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.626             eqi = None
2025-07-02 06:41:17.626
2025-07-02 06:41:17.626         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.626         # identical
2025-07-02 06:41:17.626
2025-07-02 06:41:17.626         # pump out diffs from before the synch point
2025-07-02 06:41:17.626         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.626
2025-07-02 06:41:17.626         # do intraline marking on the synch pair
2025-07-02 06:41:17.626         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.626         if eqi is None:
2025-07-02 06:41:17.626             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.626             atags = btags = ""
2025-07-02 06:41:17.626             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.626             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.626                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.626                 if tag == 'replace':
2025-07-02 06:41:17.626                     atags += '^' * la
2025-07-02 06:41:17.627                     btags += '^' * lb
2025-07-02 06:41:17.627                 elif tag == 'delete':
2025-07-02 06:41:17.627                     atags += '-' * la
2025-07-02 06:41:17.627                 elif tag == 'insert':
2025-07-02 06:41:17.627                     btags += '+' * lb
2025-07-02 06:41:17.627                 elif tag == 'equal':
2025-07-02 06:41:17.627                     atags += ' ' * la
2025-07-02 06:41:17.627                     btags += ' ' * lb
2025-07-02 06:41:17.627                 else:
2025-07-02 06:41:17.627                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.627             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.627         else:
2025-07-02 06:41:17.627             # the synch pair is identical
2025-07-02 06:41:17.627             yield '  ' + aelt
2025-07-02 06:41:17.627
2025-07-02 06:41:17.627         # pump out diffs from after the synch point
2025-07-02 06:41:17.627 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.627
2025-07-02 06:41:17.627 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.627 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.627
2025-07-02 06:41:17.628 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.628 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.628 alo = 261, ahi = 1101
2025-07-02 06:41:17.628 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.628 blo = 261, bhi = 1101
2025-07-02 06:41:17.628
2025-07-02 06:41:17.628     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.628         g = []
2025-07-02 06:41:17.628         if alo < ahi:
2025-07-02 06:41:17.628             if blo < bhi:
2025-07-02 06:41:17.628                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.628             else:
2025-07-02 06:41:17.628                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.628         elif blo < bhi:
2025-07-02 06:41:17.628             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.628
2025-07-02 06:41:17.628 >       yield from g
2025-07-02 06:41:17.628
2025-07-02 06:41:17.628 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.628 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.629
2025-07-02 06:41:17.629 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.629 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.629 alo = 261, ahi = 1101
2025-07-02 06:41:17.629 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.629 blo = 261, bhi = 1101
2025-07-02 06:41:17.629
2025-07-02 06:41:17.629     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.629         r"""
2025-07-02 06:41:17.629         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.629         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.629         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.629         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.629
2025-07-02 06:41:17.629         Example:
2025-07-02 06:41:17.629
2025-07-02 06:41:17.629         >>> d = Differ()
2025-07-02 06:41:17.629         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.629         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.629         >>> print(''.join(results), end="")
2025-07-02 06:41:17.630         - abcDefghiJkl
2025-07-02 06:41:17.630         + abcdefGhijkl
2025-07-02 06:41:17.630         """
2025-07-02 06:41:17.630
2025-07-02 06:41:17.630         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.630         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.630         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.630         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.630         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.630
2025-07-02 06:41:17.630         # search for the pair that matches best without being identical
2025-07-02 06:41:17.630         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.630         # on junk -- unless we have to)
2025-07-02 06:41:17.630         for j in range(blo, bhi):
2025-07-02 06:41:17.630             bj = b[j]
2025-07-02 06:41:17.630             cruncher.set_seq2(bj)
2025-07-02 06:41:17.630             for i in range(alo, ahi):
2025-07-02 06:41:17.630                 ai = a[i]
2025-07-02 06:41:17.631                 if ai == bj:
2025-07-02 06:41:17.631                     if eqi is None:
2025-07-02 06:41:17.631                         eqi, eqj = i, j
2025-07-02 06:41:17.631                     continue
2025-07-02 06:41:17.631                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.631                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.631                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.631                 # compares by a factor of 3.
2025-07-02 06:41:17.631                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.631                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.631                 # of the computation is cached by cruncher
2025-07-02 06:41:17.631                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.631                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.631                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.631                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.631         if best_ratio < cutoff:
2025-07-02 06:41:17.631             # no non-identical "pretty close" pair
2025-07-02 06:41:17.631             if eqi is None:
2025-07-02 06:41:17.632                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.632                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.632                 return
2025-07-02 06:41:17.632             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.632             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.632         else:
2025-07-02 06:41:17.632             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.632             eqi = None
2025-07-02 06:41:17.632
2025-07-02 06:41:17.632         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.632         # identical
2025-07-02 06:41:17.632
2025-07-02 06:41:17.632         # pump out diffs from before the synch point
2025-07-02 06:41:17.632         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.632
2025-07-02 06:41:17.632         # do intraline marking on the synch pair
2025-07-02 06:41:17.632         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.632         if eqi is None:
2025-07-02 06:41:17.632             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.632             atags = btags = ""
2025-07-02 06:41:17.633             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.633             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.633                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.633                 if tag == 'replace':
2025-07-02 06:41:17.633                     atags += '^' * la
2025-07-02 06:41:17.633                     btags += '^' * lb
2025-07-02 06:41:17.633                 elif tag == 'delete':
2025-07-02 06:41:17.633                     atags += '-' * la
2025-07-02 06:41:17.633                 elif tag == 'insert':
2025-07-02 06:41:17.633                     btags += '+' * lb
2025-07-02 06:41:17.633                 elif tag == 'equal':
2025-07-02 06:41:17.633                     atags += ' ' * la
2025-07-02 06:41:17.633                     btags += ' ' * lb
2025-07-02 06:41:17.633                 else:
2025-07-02 06:41:17.633                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.633             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.633         else:
2025-07-02 06:41:17.633             # the synch pair is identical
2025-07-02 06:41:17.633             yield '  ' + aelt
2025-07-02 06:41:17.634
2025-07-02 06:41:17.634         # pump out diffs from after the synch point
2025-07-02 06:41:17.634 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.634
2025-07-02 06:41:17.634 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.634 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.634
2025-07-02 06:41:17.634 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.634 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.634 alo = 262, ahi = 1101
2025-07-02 06:41:17.634 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.634 blo = 262, bhi = 1101
2025-07-02 06:41:17.634
2025-07-02 06:41:17.634     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.634         g = []
2025-07-02 06:41:17.634         if alo < ahi:
2025-07-02 06:41:17.634             if blo < bhi:
2025-07-02 06:41:17.634                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.634             else:
2025-07-02 06:41:17.634                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.635         elif blo < bhi:
2025-07-02 06:41:17.635             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.635
2025-07-02 06:41:17.635 >       yield from g
2025-07-02 06:41:17.635
2025-07-02 06:41:17.635 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.635 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.635
2025-07-02 06:41:17.635 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.635 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.635 alo = 262, ahi = 1101
2025-07-02 06:41:17.635 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.635 blo = 262, bhi = 1101
2025-07-02 06:41:17.635
2025-07-02 06:41:17.635     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.635         r"""
2025-07-02 06:41:17.635         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.635         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.636         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.636         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.636
2025-07-02 06:41:17.636         Example:
2025-07-02 06:41:17.636
2025-07-02 06:41:17.636         >>> d = Differ()
2025-07-02 06:41:17.636         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.636         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.636         >>> print(''.join(results), end="")
2025-07-02 06:41:17.636         - abcDefghiJkl
2025-07-02 06:41:17.636         + abcdefGhijkl
2025-07-02 06:41:17.636         """
2025-07-02 06:41:17.636
2025-07-02 06:41:17.636         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.636         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.636         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.636         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.636         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.637
2025-07-02 06:41:17.637         # search for the pair that matches best without being identical
2025-07-02 06:41:17.637         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.637         # on junk -- unless we have to)
2025-07-02 06:41:17.637         for j in range(blo, bhi):
2025-07-02 06:41:17.637             bj = b[j]
2025-07-02 06:41:17.637             cruncher.set_seq2(bj)
2025-07-02 06:41:17.637             for i in range(alo, ahi):
2025-07-02 06:41:17.637                 ai = a[i]
2025-07-02 06:41:17.637                 if ai == bj:
2025-07-02 06:41:17.637                     if eqi is None:
2025-07-02 06:41:17.637                         eqi, eqj = i, j
2025-07-02 06:41:17.637                     continue
2025-07-02 06:41:17.637                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.637                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.637                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.637                 # compares by a factor of 3.
2025-07-02 06:41:17.637                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.637                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.637                 # of the computation is cached by cruncher
2025-07-02 06:41:17.638                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.638                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.638                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.638                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.638         if best_ratio < cutoff:
2025-07-02 06:41:17.638             # no non-identical "pretty close" pair
2025-07-02 06:41:17.638             if eqi is None:
2025-07-02 06:41:17.638                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.638                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.638                 return
2025-07-02 06:41:17.638             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.638             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.638         else:
2025-07-02 06:41:17.638             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.638             eqi = None
2025-07-02 06:41:17.638
2025-07-02 06:41:17.638         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.638         # identical
2025-07-02 06:41:17.638
2025-07-02 06:41:17.638         # pump out diffs from before the synch point
2025-07-02 06:41:17.639         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.639
2025-07-02 06:41:17.639         # do intraline marking on the synch pair
2025-07-02 06:41:17.639         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.639         if eqi is None:
2025-07-02 06:41:17.639             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.639             atags = btags = ""
2025-07-02 06:41:17.639             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.639             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.639                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.639                 if tag == 'replace':
2025-07-02 06:41:17.639                     atags += '^' * la
2025-07-02 06:41:17.639                     btags += '^' * lb
2025-07-02 06:41:17.639                 elif tag == 'delete':
2025-07-02 06:41:17.639                     atags += '-' * la
2025-07-02 06:41:17.639                 elif tag == 'insert':
2025-07-02 06:41:17.639                     btags += '+' * lb
2025-07-02 06:41:17.639                 elif tag == 'equal':
2025-07-02 06:41:17.639                     atags += ' ' * la
2025-07-02 06:41:17.640                     btags += ' ' * lb
2025-07-02 06:41:17.640                 else:
2025-07-02 06:41:17.640                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.640             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.640         else:
2025-07-02 06:41:17.640             # the synch pair is identical
2025-07-02 06:41:17.640             yield '  ' + aelt
2025-07-02 06:41:17.640
2025-07-02 06:41:17.640         # pump out diffs from after the synch point
2025-07-02 06:41:17.640 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.640
2025-07-02 06:41:17.640 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.640 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.640
2025-07-02 06:41:17.640 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.640 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.640 alo = 263, ahi = 1101
2025-07-02 06:41:17.640 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.640 blo = 263, bhi = 1101
2025-07-02 06:41:17.641
2025-07-02 06:41:17.641     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.641         g = []
2025-07-02 06:41:17.641         if alo < ahi:
2025-07-02 06:41:17.641             if blo < bhi:
2025-07-02 06:41:17.641                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.641             else:
2025-07-02 06:41:17.641                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.641         elif blo < bhi:
2025-07-02 06:41:17.641             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.641
2025-07-02 06:41:17.641 >       yield from g
2025-07-02 06:41:17.641
2025-07-02 06:41:17.641 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.641 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.641
2025-07-02 06:41:17.641 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.641 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.641 alo = 263, ahi = 1101
2025-07-02 06:41:17.641 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.642 blo = 263, bhi = 1101
2025-07-02 06:41:17.642
2025-07-02 06:41:17.642     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.642         r"""
2025-07-02 06:41:17.642         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.642         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.642         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.642         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.642
2025-07-02 06:41:17.642         Example:
2025-07-02 06:41:17.642
2025-07-02 06:41:17.642         >>> d = Differ()
2025-07-02 06:41:17.642         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.642         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.642         >>> print(''.join(results), end="")
2025-07-02 06:41:17.642         - abcDefghiJkl
2025-07-02 06:41:17.642         + abcdefGhijkl
2025-07-02 06:41:17.642         """
2025-07-02 06:41:17.643
2025-07-02 06:41:17.643         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.643         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.643         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.643         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.643         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.643
2025-07-02 06:41:17.643         # search for the pair that matches best without being identical
2025-07-02 06:41:17.643         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.643         # on junk -- unless we have to)
2025-07-02 06:41:17.643         for j in range(blo, bhi):
2025-07-02 06:41:17.643             bj = b[j]
2025-07-02 06:41:17.643             cruncher.set_seq2(bj)
2025-07-02 06:41:17.643             for i in range(alo, ahi):
2025-07-02 06:41:17.643                 ai = a[i]
2025-07-02 06:41:17.643                 if ai == bj:
2025-07-02 06:41:17.643                     if eqi is None:
2025-07-02 06:41:17.643                         eqi, eqj = i, j
2025-07-02 06:41:17.644                     continue
2025-07-02 06:41:17.644                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.644                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.644                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.644                 # compares by a factor of 3.
2025-07-02 06:41:17.644                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.644                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.644                 # of the computation is cached by cruncher
2025-07-02 06:41:17.644                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.644                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.644                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.644                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.644         if best_ratio < cutoff:
2025-07-02 06:41:17.644             # no non-identical "pretty close" pair
2025-07-02 06:41:17.644             if eqi is None:
2025-07-02 06:41:17.644                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.644                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.644                 return
2025-07-02 06:41:17.644             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.644             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.645         else:
2025-07-02 06:41:17.645             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.645             eqi = None
2025-07-02 06:41:17.645
2025-07-02 06:41:17.645         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.645         # identical
2025-07-02 06:41:17.645
2025-07-02 06:41:17.645         # pump out diffs from before the synch point
2025-07-02 06:41:17.645         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.645
2025-07-02 06:41:17.645         # do intraline marking on the synch pair
2025-07-02 06:41:17.645         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.645         if eqi is None:
2025-07-02 06:41:17.645             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.645             atags = btags = ""
2025-07-02 06:41:17.645             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.645             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.645                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.645                 if tag == 'replace':
2025-07-02 06:41:17.645                     atags += '^' * la
2025-07-02 06:41:17.646                     btags += '^' * lb
2025-07-02 06:41:17.646                 elif tag == 'delete':
2025-07-02 06:41:17.646                     atags += '-' * la
2025-07-02 06:41:17.646                 elif tag == 'insert':
2025-07-02 06:41:17.646                     btags += '+' * lb
2025-07-02 06:41:17.646                 elif tag == 'equal':
2025-07-02 06:41:17.646                     atags += ' ' * la
2025-07-02 06:41:17.646                     btags += ' ' * lb
2025-07-02 06:41:17.646                 else:
2025-07-02 06:41:17.646                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.646             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.646         else:
2025-07-02 06:41:17.646             # the synch pair is identical
2025-07-02 06:41:17.646             yield '  ' + aelt
2025-07-02 06:41:17.646
2025-07-02 06:41:17.646         # pump out diffs from after the synch point
2025-07-02 06:41:17.646 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.646
2025-07-02 06:41:17.646 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.647 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.647
2025-07-02 06:41:17.647 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.647 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.647 alo = 264, ahi = 1101
2025-07-02 06:41:17.647 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.647 blo = 264, bhi = 1101
2025-07-02 06:41:17.647
2025-07-02 06:41:17.647     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.647         g = []
2025-07-02 06:41:17.647         if alo < ahi:
2025-07-02 06:41:17.647             if blo < bhi:
2025-07-02 06:41:17.647                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.647             else:
2025-07-02 06:41:17.647                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.647         elif blo < bhi:
2025-07-02 06:41:17.647             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.647
2025-07-02 06:41:17.647 >       yield from g
2025-07-02 06:41:17.648
2025-07-02 06:41:17.648 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.648 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.648
2025-07-02 06:41:17.648 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.648 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.648 alo = 264, ahi = 1101
2025-07-02 06:41:17.648 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.648 blo = 264, bhi = 1101
2025-07-02 06:41:17.648
2025-07-02 06:41:17.648     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.648         r"""
2025-07-02 06:41:17.648         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.648         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.648         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.648         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.648
2025-07-02 06:41:17.648         Example:
2025-07-02 06:41:17.649
2025-07-02 06:41:17.649         >>> d = Differ()
2025-07-02 06:41:17.649         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.649         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.649         >>> print(''.join(results), end="")
2025-07-02 06:41:17.649         - abcDefghiJkl
2025-07-02 06:41:17.649         + abcdefGhijkl
2025-07-02 06:41:17.649         """
2025-07-02 06:41:17.649
2025-07-02 06:41:17.649         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.649         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.649         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.649         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.649         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.649
2025-07-02 06:41:17.649         # search for the pair that matches best without being identical
2025-07-02 06:41:17.649         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.650         # on junk -- unless we have to)
2025-07-02 06:41:17.650         for j in range(blo, bhi):
2025-07-02 06:41:17.650             bj = b[j]
2025-07-02 06:41:17.650             cruncher.set_seq2(bj)
2025-07-02 06:41:17.650             for i in range(alo, ahi):
2025-07-02 06:41:17.650                 ai = a[i]
2025-07-02 06:41:17.650                 if ai == bj:
2025-07-02 06:41:17.650                     if eqi is None:
2025-07-02 06:41:17.650                         eqi, eqj = i, j
2025-07-02 06:41:17.650                     continue
2025-07-02 06:41:17.650                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.650                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.650                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.650                 # compares by a factor of 3.
2025-07-02 06:41:17.650                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.650                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.650                 # of the computation is cached by cruncher
2025-07-02 06:41:17.650                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.650                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.650                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.651                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.651         if best_ratio < cutoff:
2025-07-02 06:41:17.651             # no non-identical "pretty close" pair
2025-07-02 06:41:17.651             if eqi is None:
2025-07-02 06:41:17.651                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.651                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.651                 return
2025-07-02 06:41:17.651             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.651             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.651         else:
2025-07-02 06:41:17.651             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.651             eqi = None
2025-07-02 06:41:17.651
2025-07-02 06:41:17.651         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.651         # identical
2025-07-02 06:41:17.651
2025-07-02 06:41:17.651         # pump out diffs from before the synch point
2025-07-02 06:41:17.651         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.651
2025-07-02 06:41:17.651         # do intraline marking on the synch pair
2025-07-02 06:41:17.652         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.652         if eqi is None:
2025-07-02 06:41:17.652             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.652             atags = btags = ""
2025-07-02 06:41:17.652             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.652             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.652                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.652                 if tag == 'replace':
2025-07-02 06:41:17.652                     atags += '^' * la
2025-07-02 06:41:17.652                     btags += '^' * lb
2025-07-02 06:41:17.652                 elif tag == 'delete':
2025-07-02 06:41:17.652                     atags += '-' * la
2025-07-02 06:41:17.652                 elif tag == 'insert':
2025-07-02 06:41:17.652                     btags += '+' * lb
2025-07-02 06:41:17.652                 elif tag == 'equal':
2025-07-02 06:41:17.652                     atags += ' ' * la
2025-07-02 06:41:17.652                     btags += ' ' * lb
2025-07-02 06:41:17.652                 else:
2025-07-02 06:41:17.652                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.652             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.652         else:
2025-07-02 06:41:17.653             # the synch pair is identical
2025-07-02 06:41:17.653             yield '  ' + aelt
2025-07-02 06:41:17.653
2025-07-02 06:41:17.653         # pump out diffs from after the synch point
2025-07-02 06:41:17.653 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.653
2025-07-02 06:41:17.653 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.653 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.653
2025-07-02 06:41:17.653 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.653 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.653 alo = 265, ahi = 1101
2025-07-02 06:41:17.653 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.653 blo = 265, bhi = 1101
2025-07-02 06:41:17.653
2025-07-02 06:41:17.653     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.653         g = []
2025-07-02 06:41:17.653         if alo < ahi:
2025-07-02 06:41:17.653             if blo < bhi:
2025-07-02 06:41:17.653                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.654             else:
2025-07-02 06:41:17.654                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.654         elif blo < bhi:
2025-07-02 06:41:17.654             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.654
2025-07-02 06:41:17.654 >       yield from g
2025-07-02 06:41:17.654
2025-07-02 06:41:17.654 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.654 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.654
2025-07-02 06:41:17.654 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.654 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.654 alo = 265, ahi = 1101
2025-07-02 06:41:17.654 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.654 blo = 265, bhi = 1101
2025-07-02 06:41:17.654
2025-07-02 06:41:17.654     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.654         r"""
2025-07-02 06:41:17.654         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.654         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.655         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.655         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.655
2025-07-02 06:41:17.655         Example:
2025-07-02 06:41:17.655
2025-07-02 06:41:17.655         >>> d = Differ()
2025-07-02 06:41:17.655         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.655         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.655         >>> print(''.join(results), end="")
2025-07-02 06:41:17.655         - abcDefghiJkl
2025-07-02 06:41:17.655         + abcdefGhijkl
2025-07-02 06:41:17.655         """
2025-07-02 06:41:17.655
2025-07-02 06:41:17.655         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.655         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.655         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.655         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.656         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.656
2025-07-02 06:41:17.656         # search for the pair that matches best without being identical
2025-07-02 06:41:17.656         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.656         # on junk -- unless we have to)
2025-07-02 06:41:17.656         for j in range(blo, bhi):
2025-07-02 06:41:17.656             bj = b[j]
2025-07-02 06:41:17.656             cruncher.set_seq2(bj)
2025-07-02 06:41:17.656             for i in range(alo, ahi):
2025-07-02 06:41:17.656                 ai = a[i]
2025-07-02 06:41:17.656                 if ai == bj:
2025-07-02 06:41:17.656                     if eqi is None:
2025-07-02 06:41:17.656                         eqi, eqj = i, j
2025-07-02 06:41:17.656                     continue
2025-07-02 06:41:17.656                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.656                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.656                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.656                 # compares by a factor of 3.
2025-07-02 06:41:17.656                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.657                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.657                 # of the computation is cached by cruncher
2025-07-02 06:41:17.657                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.657                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.657                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.657                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.657         if best_ratio < cutoff:
2025-07-02 06:41:17.657             # no non-identical "pretty close" pair
2025-07-02 06:41:17.657             if eqi is None:
2025-07-02 06:41:17.657                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.657                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.657                 return
2025-07-02 06:41:17.657             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.657             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.657         else:
2025-07-02 06:41:17.657             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.657             eqi = None
2025-07-02 06:41:17.657
2025-07-02 06:41:17.657         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.658         # identical
2025-07-02 06:41:17.658
2025-07-02 06:41:17.658         # pump out diffs from before the synch point
2025-07-02 06:41:17.658         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.658
2025-07-02 06:41:17.658         # do intraline marking on the synch pair
2025-07-02 06:41:17.658         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.658         if eqi is None:
2025-07-02 06:41:17.658             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.658             atags = btags = ""
2025-07-02 06:41:17.658             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.658             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.658                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.658                 if tag == 'replace':
2025-07-02 06:41:17.658                     atags += '^' * la
2025-07-02 06:41:17.658                     btags += '^' * lb
2025-07-02 06:41:17.658                 elif tag == 'delete':
2025-07-02 06:41:17.658                     atags += '-' * la
2025-07-02 06:41:17.658                 elif tag == 'insert':
2025-07-02 06:41:17.658                     btags += '+' * lb
2025-07-02 06:41:17.659                 elif tag == 'equal':
2025-07-02 06:41:17.659                     atags += ' ' * la
2025-07-02 06:41:17.659                     btags += ' ' * lb
2025-07-02 06:41:17.659                 else:
2025-07-02 06:41:17.659                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.659             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.659         else:
2025-07-02 06:41:17.659             # the synch pair is identical
2025-07-02 06:41:17.659             yield '  ' + aelt
2025-07-02 06:41:17.659
2025-07-02 06:41:17.659         # pump out diffs from after the synch point
2025-07-02 06:41:17.659 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.659
2025-07-02 06:41:17.659 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.659 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.659
2025-07-02 06:41:17.659 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.659 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.659 alo = 268, ahi = 1101
2025-07-02 06:41:17.659 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.660 blo = 268, bhi = 1101
2025-07-02 06:41:17.660
2025-07-02 06:41:17.660     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.660         g = []
2025-07-02 06:41:17.660         if alo < ahi:
2025-07-02 06:41:17.660             if blo < bhi:
2025-07-02 06:41:17.660                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.660             else:
2025-07-02 06:41:17.660                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.660         elif blo < bhi:
2025-07-02 06:41:17.660             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.660
2025-07-02 06:41:17.660 >       yield from g
2025-07-02 06:41:17.660
2025-07-02 06:41:17.660 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.660 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.660
2025-07-02 06:41:17.660 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.660 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.660 alo = 268, ahi = 1101
2025-07-02 06:41:17.661 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.661 blo = 268, bhi = 1101
2025-07-02 06:41:17.661
2025-07-02 06:41:17.661     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.661         r"""
2025-07-02 06:41:17.661         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.661         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.661         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.661         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.661
2025-07-02 06:41:17.661         Example:
2025-07-02 06:41:17.661
2025-07-02 06:41:17.661         >>> d = Differ()
2025-07-02 06:41:17.661         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.661         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.661         >>> print(''.join(results), end="")
2025-07-02 06:41:17.661         - abcDefghiJkl
2025-07-02 06:41:17.662         + abcdefGhijkl
2025-07-02 06:41:17.662         """
2025-07-02 06:41:17.662
2025-07-02 06:41:17.662         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.662         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.662         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.662         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.662         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.662
2025-07-02 06:41:17.662         # search for the pair that matches best without being identical
2025-07-02 06:41:17.662         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.662         # on junk -- unless we have to)
2025-07-02 06:41:17.662         for j in range(blo, bhi):
2025-07-02 06:41:17.662             bj = b[j]
2025-07-02 06:41:17.662             cruncher.set_seq2(bj)
2025-07-02 06:41:17.662             for i in range(alo, ahi):
2025-07-02 06:41:17.662                 ai = a[i]
2025-07-02 06:41:17.662                 if ai == bj:
2025-07-02 06:41:17.663                     if eqi is None:
2025-07-02 06:41:17.663                         eqi, eqj = i, j
2025-07-02 06:41:17.663                     continue
2025-07-02 06:41:17.663                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.663                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.663                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.663                 # compares by a factor of 3.
2025-07-02 06:41:17.663                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.663                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.663                 # of the computation is cached by cruncher
2025-07-02 06:41:17.663                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.663                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.663                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.663                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.663         if best_ratio < cutoff:
2025-07-02 06:41:17.663             # no non-identical "pretty close" pair
2025-07-02 06:41:17.663             if eqi is None:
2025-07-02 06:41:17.663                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.663                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.663                 return
2025-07-02 06:41:17.664             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.664             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.664         else:
2025-07-02 06:41:17.664             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.664             eqi = None
2025-07-02 06:41:17.664
2025-07-02 06:41:17.664         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.664         # identical
2025-07-02 06:41:17.664
2025-07-02 06:41:17.664         # pump out diffs from before the synch point
2025-07-02 06:41:17.664         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.664
2025-07-02 06:41:17.664         # do intraline marking on the synch pair
2025-07-02 06:41:17.664         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.664         if eqi is None:
2025-07-02 06:41:17.664             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.664             atags = btags = ""
2025-07-02 06:41:17.664             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.664             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.664                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.665                 if tag == 'replace':
2025-07-02 06:41:17.665                     atags += '^' * la
2025-07-02 06:41:17.665                     btags += '^' * lb
2025-07-02 06:41:17.665                 elif tag == 'delete':
2025-07-02 06:41:17.665                     atags += '-' * la
2025-07-02 06:41:17.665                 elif tag == 'insert':
2025-07-02 06:41:17.665                     btags += '+' * lb
2025-07-02 06:41:17.665                 elif tag == 'equal':
2025-07-02 06:41:17.665                     atags += ' ' * la
2025-07-02 06:41:17.665                     btags += ' ' * lb
2025-07-02 06:41:17.665                 else:
2025-07-02 06:41:17.665                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.665             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.665         else:
2025-07-02 06:41:17.665             # the synch pair is identical
2025-07-02 06:41:17.665             yield '  ' + aelt
2025-07-02 06:41:17.665
2025-07-02 06:41:17.665         # pump out diffs from after the synch point
2025-07-02 06:41:17.665 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.666
2025-07-02 06:41:17.666 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.666 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.666
2025-07-02 06:41:17.666 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.666 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.666 alo = 269, ahi = 1101
2025-07-02 06:41:17.666 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.666 blo = 269, bhi = 1101
2025-07-02 06:41:17.666
2025-07-02 06:41:17.666     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.666         g = []
2025-07-02 06:41:17.666         if alo < ahi:
2025-07-02 06:41:17.666             if blo < bhi:
2025-07-02 06:41:17.666                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.666             else:
2025-07-02 06:41:17.666                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.666         elif blo < bhi:
2025-07-02 06:41:17.666             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.667
2025-07-02 06:41:17.667 >       yield from g
2025-07-02 06:41:17.667
2025-07-02 06:41:17.667 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.667 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.667
2025-07-02 06:41:17.667 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.667 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.667 alo = 269, ahi = 1101
2025-07-02 06:41:17.667 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.667 blo = 269, bhi = 1101
2025-07-02 06:41:17.667
2025-07-02 06:41:17.667     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.667         r"""
2025-07-02 06:41:17.667         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.667         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.667         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.667         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.667
2025-07-02 06:41:17.668         Example:
2025-07-02 06:41:17.668
2025-07-02 06:41:17.668         >>> d = Differ()
2025-07-02 06:41:17.668         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.668         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.668         >>> print(''.join(results), end="")
2025-07-02 06:41:17.668         - abcDefghiJkl
2025-07-02 06:41:17.668         + abcdefGhijkl
2025-07-02 06:41:17.668         """
2025-07-02 06:41:17.668
2025-07-02 06:41:17.668         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.668         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.668         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.668         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.668         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.668
2025-07-02 06:41:17.668         # search for the pair that matches best without being identical
2025-07-02 06:41:17.668         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.668         # on junk -- unless we have to)
2025-07-02 06:41:17.669         for j in range(blo, bhi):
2025-07-02 06:41:17.669             bj = b[j]
2025-07-02 06:41:17.669             cruncher.set_seq2(bj)
2025-07-02 06:41:17.669             for i in range(alo, ahi):
2025-07-02 06:41:17.669                 ai = a[i]
2025-07-02 06:41:17.669                 if ai == bj:
2025-07-02 06:41:17.669                     if eqi is None:
2025-07-02 06:41:17.669                         eqi, eqj = i, j
2025-07-02 06:41:17.669                     continue
2025-07-02 06:41:17.669                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.669                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.669                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.669                 # compares by a factor of 3.
2025-07-02 06:41:17.669                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.669                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.669                 # of the computation is cached by cruncher
2025-07-02 06:41:17.669                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.669                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.669                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.669                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.670         if best_ratio < cutoff:
2025-07-02 06:41:17.670             # no non-identical "pretty close" pair
2025-07-02 06:41:17.670             if eqi is None:
2025-07-02 06:41:17.670                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.670                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.670                 return
2025-07-02 06:41:17.670             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.670             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.670         else:
2025-07-02 06:41:17.670             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.670             eqi = None
2025-07-02 06:41:17.670
2025-07-02 06:41:17.670         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.670         # identical
2025-07-02 06:41:17.670
2025-07-02 06:41:17.670         # pump out diffs from before the synch point
2025-07-02 06:41:17.670         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.670
2025-07-02 06:41:17.670         # do intraline marking on the synch pair
2025-07-02 06:41:17.670         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.671         if eqi is None:
2025-07-02 06:41:17.671             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.671             atags = btags = ""
2025-07-02 06:41:17.671             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.671             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.671                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.671                 if tag == 'replace':
2025-07-02 06:41:17.671                     atags += '^' * la
2025-07-02 06:41:17.671                     btags += '^' * lb
2025-07-02 06:41:17.671                 elif tag == 'delete':
2025-07-02 06:41:17.671                     atags += '-' * la
2025-07-02 06:41:17.671                 elif tag == 'insert':
2025-07-02 06:41:17.671                     btags += '+' * lb
2025-07-02 06:41:17.671                 elif tag == 'equal':
2025-07-02 06:41:17.671                     atags += ' ' * la
2025-07-02 06:41:17.671                     btags += ' ' * lb
2025-07-02 06:41:17.671                 else:
2025-07-02 06:41:17.671                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.671             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.671         else:
2025-07-02 06:41:17.671             # the synch pair is identical
2025-07-02 06:41:17.672             yield '  ' + aelt
2025-07-02 06:41:17.672
2025-07-02 06:41:17.672         # pump out diffs from after the synch point
2025-07-02 06:41:17.672 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.672
2025-07-02 06:41:17.672 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.672 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.672
2025-07-02 06:41:17.672 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.672 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.672 alo = 270, ahi = 1101
2025-07-02 06:41:17.672 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.672 blo = 270, bhi = 1101
2025-07-02 06:41:17.672
2025-07-02 06:41:17.672     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.672         g = []
2025-07-02 06:41:17.672         if alo < ahi:
2025-07-02 06:41:17.672             if blo < bhi:
2025-07-02 06:41:17.672                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.672             else:
2025-07-02 06:41:17.673                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.673         elif blo < bhi:
2025-07-02 06:41:17.673             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.673
2025-07-02 06:41:17.673 >       yield from g
2025-07-02 06:41:17.673
2025-07-02 06:41:17.673 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.673 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.673
2025-07-02 06:41:17.673 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.673 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.673 alo = 270, ahi = 1101
2025-07-02 06:41:17.673 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.673 blo = 270, bhi = 1101
2025-07-02 06:41:17.673
2025-07-02 06:41:17.673     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.673         r"""
2025-07-02 06:41:17.673         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.673         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.673         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.674         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.674
2025-07-02 06:41:17.674         Example:
2025-07-02 06:41:17.674
2025-07-02 06:41:17.674         >>> d = Differ()
2025-07-02 06:41:17.674         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.674         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.674         >>> print(''.join(results), end="")
2025-07-02 06:41:17.674         - abcDefghiJkl
2025-07-02 06:41:17.674         + abcdefGhijkl
2025-07-02 06:41:17.674         """
2025-07-02 06:41:17.674
2025-07-02 06:41:17.674         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.674         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.674         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.674         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.675         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.675
2025-07-02 06:41:17.675         # search for the pair that matches best without being identical
2025-07-02 06:41:17.675         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.675         # on junk -- unless we have to)
2025-07-02 06:41:17.675         for j in range(blo, bhi):
2025-07-02 06:41:17.675             bj = b[j]
2025-07-02 06:41:17.675             cruncher.set_seq2(bj)
2025-07-02 06:41:17.675             for i in range(alo, ahi):
2025-07-02 06:41:17.675                 ai = a[i]
2025-07-02 06:41:17.675                 if ai == bj:
2025-07-02 06:41:17.675                     if eqi is None:
2025-07-02 06:41:17.675                         eqi, eqj = i, j
2025-07-02 06:41:17.675                     continue
2025-07-02 06:41:17.675                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.675                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.675                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.675                 # compares by a factor of 3.
2025-07-02 06:41:17.675                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.676                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.676                 # of the computation is cached by cruncher
2025-07-02 06:41:17.676                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.676                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.676                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.676                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.676         if best_ratio < cutoff:
2025-07-02 06:41:17.676             # no non-identical "pretty close" pair
2025-07-02 06:41:17.676             if eqi is None:
2025-07-02 06:41:17.676                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.676                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.676                 return
2025-07-02 06:41:17.676             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.676             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.676         else:
2025-07-02 06:41:17.676             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.676             eqi = None
2025-07-02 06:41:17.676
2025-07-02 06:41:17.676         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.676         # identical
2025-07-02 06:41:17.677
2025-07-02 06:41:17.677         # pump out diffs from before the synch point
2025-07-02 06:41:17.677         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.677
2025-07-02 06:41:17.677         # do intraline marking on the synch pair
2025-07-02 06:41:17.677         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.677         if eqi is None:
2025-07-02 06:41:17.677             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.677             atags = btags = ""
2025-07-02 06:41:17.677             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.677             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.677                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.677                 if tag == 'replace':
2025-07-02 06:41:17.677                     atags += '^' * la
2025-07-02 06:41:17.677                     btags += '^' * lb
2025-07-02 06:41:17.677                 elif tag == 'delete':
2025-07-02 06:41:17.677                     atags += '-' * la
2025-07-02 06:41:17.678                 elif tag == 'insert':
2025-07-02 06:41:17.678                     btags += '+' * lb
2025-07-02 06:41:17.678                 elif tag == 'equal':
2025-07-02 06:41:17.678                     atags += ' ' * la
2025-07-02 06:41:17.678                     btags += ' ' * lb
2025-07-02 06:41:17.678                 else:
2025-07-02 06:41:17.678                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.678             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.678         else:
2025-07-02 06:41:17.678             # the synch pair is identical
2025-07-02 06:41:17.678             yield '  ' + aelt
2025-07-02 06:41:17.678
2025-07-02 06:41:17.678         # pump out diffs from after the synch point
2025-07-02 06:41:17.678 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.678
2025-07-02 06:41:17.678 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.678 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.678
2025-07-02 06:41:17.678 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.678 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.679 alo = 271, ahi = 1101
2025-07-02 06:41:17.679 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.679 blo = 271, bhi = 1101
2025-07-02 06:41:17.679
2025-07-02 06:41:17.679     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.679         g = []
2025-07-02 06:41:17.679         if alo < ahi:
2025-07-02 06:41:17.679             if blo < bhi:
2025-07-02 06:41:17.679                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.679             else:
2025-07-02 06:41:17.679                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.679         elif blo < bhi:
2025-07-02 06:41:17.679             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.679
2025-07-02 06:41:17.679 >       yield from g
2025-07-02 06:41:17.679
2025-07-02 06:41:17.679 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.679 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.679
2025-07-02 06:41:17.679 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.680 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.680 alo = 271, ahi = 1101
2025-07-02 06:41:17.680 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.680 blo = 271, bhi = 1101
2025-07-02 06:41:17.680
2025-07-02 06:41:17.680     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.680         r"""
2025-07-02 06:41:17.680         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.680         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.680         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.680         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.680
2025-07-02 06:41:17.680         Example:
2025-07-02 06:41:17.680
2025-07-02 06:41:17.680         >>> d = Differ()
2025-07-02 06:41:17.680         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.680         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.680         >>> print(''.join(results), end="")
2025-07-02 06:41:17.680         - abcDefghiJkl
2025-07-02 06:41:17.680         + abcdefGhijkl
2025-07-02 06:41:17.681         """
2025-07-02 06:41:17.681
2025-07-02 06:41:17.681         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.681         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.681         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.681         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.681         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.681
2025-07-02 06:41:17.681         # search for the pair that matches best without being identical
2025-07-02 06:41:17.681         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.681         # on junk -- unless we have to)
2025-07-02 06:41:17.681         for j in range(blo, bhi):
2025-07-02 06:41:17.681             bj = b[j]
2025-07-02 06:41:17.681             cruncher.set_seq2(bj)
2025-07-02 06:41:17.681             for i in range(alo, ahi):
2025-07-02 06:41:17.681                 ai = a[i]
2025-07-02 06:41:17.681                 if ai == bj:
2025-07-02 06:41:17.681                     if eqi is None:
2025-07-02 06:41:17.681                         eqi, eqj = i, j
2025-07-02 06:41:17.682                     continue
2025-07-02 06:41:17.682                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.682                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.682                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.682                 # compares by a factor of 3.
2025-07-02 06:41:17.682                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.682                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.682                 # of the computation is cached by cruncher
2025-07-02 06:41:17.682                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.682                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.682                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.682                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.682         if best_ratio < cutoff:
2025-07-02 06:41:17.682             # no non-identical "pretty close" pair
2025-07-02 06:41:17.682             if eqi is None:
2025-07-02 06:41:17.682                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.682                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.682                 return
2025-07-02 06:41:17.682             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.682             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.682         else:
2025-07-02 06:41:17.683             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.683             eqi = None
2025-07-02 06:41:17.683
2025-07-02 06:41:17.683         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.683         # identical
2025-07-02 06:41:17.683
2025-07-02 06:41:17.683         # pump out diffs from before the synch point
2025-07-02 06:41:17.683         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.683
2025-07-02 06:41:17.683         # do intraline marking on the synch pair
2025-07-02 06:41:17.683         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.683         if eqi is None:
2025-07-02 06:41:17.683             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.683             atags = btags = ""
2025-07-02 06:41:17.683             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.683             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.683                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.683                 if tag == 'replace':
2025-07-02 06:41:17.684                     atags += '^' * la
2025-07-02 06:41:17.684                     btags += '^' * lb
2025-07-02 06:41:17.684                 elif tag == 'delete':
2025-07-02 06:41:17.684                     atags += '-' * la
2025-07-02 06:41:17.684                 elif tag == 'insert':
2025-07-02 06:41:17.684                     btags += '+' * lb
2025-07-02 06:41:17.684                 elif tag == 'equal':
2025-07-02 06:41:17.684                     atags += ' ' * la
2025-07-02 06:41:17.684                     btags += ' ' * lb
2025-07-02 06:41:17.684                 else:
2025-07-02 06:41:17.684                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.684             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.684         else:
2025-07-02 06:41:17.684             # the synch pair is identical
2025-07-02 06:41:17.684             yield '  ' + aelt
2025-07-02 06:41:17.684
2025-07-02 06:41:17.684         # pump out diffs from after the synch point
2025-07-02 06:41:17.684 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.684
2025-07-02 06:41:17.685 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.685 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.685
2025-07-02 06:41:17.685 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.685 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.685 alo = 272, ahi = 1101
2025-07-02 06:41:17.685 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.685 blo = 272, bhi = 1101
2025-07-02 06:41:17.685
2025-07-02 06:41:17.685     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.685         g = []
2025-07-02 06:41:17.685         if alo < ahi:
2025-07-02 06:41:17.685             if blo < bhi:
2025-07-02 06:41:17.685                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.685             else:
2025-07-02 06:41:17.685                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.685         elif blo < bhi:
2025-07-02 06:41:17.685             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.685
2025-07-02 06:41:17.685 >       yield from g
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.686 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.686 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.686 alo = 272, ahi = 1101
2025-07-02 06:41:17.686 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.686 blo = 272, bhi = 1101
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.686         r"""
2025-07-02 06:41:17.686         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.686         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.686         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.686         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686         Example:
2025-07-02 06:41:17.686
2025-07-02 06:41:17.686         >>> d = Differ()
2025-07-02 06:41:17.687         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.687         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.687         >>> print(''.join(results), end="")
2025-07-02 06:41:17.687         - abcDefghiJkl
2025-07-02 06:41:17.687         + abcdefGhijkl
2025-07-02 06:41:17.687         """
2025-07-02 06:41:17.687
2025-07-02 06:41:17.687         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.687         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.687         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.687         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.687         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.687
2025-07-02 06:41:17.687         # search for the pair that matches best without being identical
2025-07-02 06:41:17.687         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.687         # on junk -- unless we have to)
2025-07-02 06:41:17.687         for j in range(blo, bhi):
2025-07-02 06:41:17.687             bj = b[j]
2025-07-02 06:41:17.687             cruncher.set_seq2(bj)
2025-07-02 06:41:17.688             for i in range(alo, ahi):
2025-07-02 06:41:17.688                 ai = a[i]
2025-07-02 06:41:17.688                 if ai == bj:
2025-07-02 06:41:17.688                     if eqi is None:
2025-07-02 06:41:17.688                         eqi, eqj = i, j
2025-07-02 06:41:17.688                     continue
2025-07-02 06:41:17.688                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.688                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.688                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.688                 # compares by a factor of 3.
2025-07-02 06:41:17.688                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.688                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.688                 # of the computation is cached by cruncher
2025-07-02 06:41:17.688                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.688                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.688                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.688                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.688         if best_ratio < cutoff:
2025-07-02 06:41:17.688             # no non-identical "pretty close" pair
2025-07-02 06:41:17.689             if eqi is None:
2025-07-02 06:41:17.689                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.689                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.689                 return
2025-07-02 06:41:17.689             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.689             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.689         else:
2025-07-02 06:41:17.689             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.689             eqi = None
2025-07-02 06:41:17.689
2025-07-02 06:41:17.689         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.689         # identical
2025-07-02 06:41:17.689
2025-07-02 06:41:17.689         # pump out diffs from before the synch point
2025-07-02 06:41:17.689         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.689
2025-07-02 06:41:17.689         # do intraline marking on the synch pair
2025-07-02 06:41:17.689         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.689         if eqi is None:
2025-07-02 06:41:17.689             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.690             atags = btags = ""
2025-07-02 06:41:17.690             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.690             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.690                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.690                 if tag == 'replace':
2025-07-02 06:41:17.690                     atags += '^' * la
2025-07-02 06:41:17.690                     btags += '^' * lb
2025-07-02 06:41:17.690                 elif tag == 'delete':
2025-07-02 06:41:17.690                     atags += '-' * la
2025-07-02 06:41:17.690                 elif tag == 'insert':
2025-07-02 06:41:17.690                     btags += '+' * lb
2025-07-02 06:41:17.690                 elif tag == 'equal':
2025-07-02 06:41:17.690                     atags += ' ' * la
2025-07-02 06:41:17.690                     btags += ' ' * lb
2025-07-02 06:41:17.690                 else:
2025-07-02 06:41:17.690                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.690             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.690         else:
2025-07-02 06:41:17.690             # the synch pair is identical
2025-07-02 06:41:17.690             yield '  ' + aelt
2025-07-02 06:41:17.690
2025-07-02 06:41:17.691         # pump out diffs from after the synch point
2025-07-02 06:41:17.691 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.691
2025-07-02 06:41:17.691 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.691 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.691
2025-07-02 06:41:17.691 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.691 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.691 alo = 273, ahi = 1101
2025-07-02 06:41:17.691 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.691 blo = 273, bhi = 1101
2025-07-02 06:41:17.691
2025-07-02 06:41:17.691     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.691         g = []
2025-07-02 06:41:17.691         if alo < ahi:
2025-07-02 06:41:17.691             if blo < bhi:
2025-07-02 06:41:17.691                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.691             else:
2025-07-02 06:41:17.691                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.692         elif blo < bhi:
2025-07-02 06:41:17.692             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.692
2025-07-02 06:41:17.692 >       yield from g
2025-07-02 06:41:17.692
2025-07-02 06:41:17.692 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.692 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.692
2025-07-02 06:41:17.692 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.692 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.692 alo = 273, ahi = 1101
2025-07-02 06:41:17.692 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.692 blo = 273, bhi = 1101
2025-07-02 06:41:17.692
2025-07-02 06:41:17.692     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.692         r"""
2025-07-02 06:41:17.692         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.692         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.692         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.693         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.693
2025-07-02 06:41:17.693         Example:
2025-07-02 06:41:17.693
2025-07-02 06:41:17.693         >>> d = Differ()
2025-07-02 06:41:17.693         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.693         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.693         >>> print(''.join(results), end="")
2025-07-02 06:41:17.693         - abcDefghiJkl
2025-07-02 06:41:17.693         + abcdefGhijkl
2025-07-02 06:41:17.693         """
2025-07-02 06:41:17.693
2025-07-02 06:41:17.693         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.693         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.693         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.693         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.693         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.694
2025-07-02 06:41:17.694         # search for the pair that matches best without being identical
2025-07-02 06:41:17.694         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.694         # on junk -- unless we have to)
2025-07-02 06:41:17.694         for j in range(blo, bhi):
2025-07-02 06:41:17.694             bj = b[j]
2025-07-02 06:41:17.694             cruncher.set_seq2(bj)
2025-07-02 06:41:17.694             for i in range(alo, ahi):
2025-07-02 06:41:17.694                 ai = a[i]
2025-07-02 06:41:17.694                 if ai == bj:
2025-07-02 06:41:17.694                     if eqi is None:
2025-07-02 06:41:17.694                         eqi, eqj = i, j
2025-07-02 06:41:17.694                     continue
2025-07-02 06:41:17.694                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.694                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.694                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.694                 # compares by a factor of 3.
2025-07-02 06:41:17.694                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.694                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.694                 # of the computation is cached by cruncher
2025-07-02 06:41:17.695                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.695                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.695                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.695                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.695         if best_ratio < cutoff:
2025-07-02 06:41:17.695             # no non-identical "pretty close" pair
2025-07-02 06:41:17.695             if eqi is None:
2025-07-02 06:41:17.695                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.695                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.695                 return
2025-07-02 06:41:17.695             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.695             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.695         else:
2025-07-02 06:41:17.695             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.695             eqi = None
2025-07-02 06:41:17.695
2025-07-02 06:41:17.695         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.695         # identical
2025-07-02 06:41:17.695
2025-07-02 06:41:17.695         # pump out diffs from before the synch point
2025-07-02 06:41:17.696         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.696
2025-07-02 06:41:17.696         # do intraline marking on the synch pair
2025-07-02 06:41:17.696         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.696         if eqi is None:
2025-07-02 06:41:17.696             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.696             atags = btags = ""
2025-07-02 06:41:17.696             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.696             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.696                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.696                 if tag == 'replace':
2025-07-02 06:41:17.696                     atags += '^' * la
2025-07-02 06:41:17.696                     btags += '^' * lb
2025-07-02 06:41:17.696                 elif tag == 'delete':
2025-07-02 06:41:17.696                     atags += '-' * la
2025-07-02 06:41:17.696                 elif tag == 'insert':
2025-07-02 06:41:17.696                     btags += '+' * lb
2025-07-02 06:41:17.696                 elif tag == 'equal':
2025-07-02 06:41:17.696                     atags += ' ' * la
2025-07-02 06:41:17.696                     btags += ' ' * lb
2025-07-02 06:41:17.697                 else:
2025-07-02 06:41:17.697                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.697             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.697         else:
2025-07-02 06:41:17.697             # the synch pair is identical
2025-07-02 06:41:17.697             yield '  ' + aelt
2025-07-02 06:41:17.697
2025-07-02 06:41:17.697         # pump out diffs from after the synch point
2025-07-02 06:41:17.697 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.697
2025-07-02 06:41:17.697 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.697 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.697
2025-07-02 06:41:17.697 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.697 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.697 alo = 274, ahi = 1101
2025-07-02 06:41:17.697 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.697 blo = 274, bhi = 1101
2025-07-02 06:41:17.697
2025-07-02 06:41:17.697     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.698         g = []
2025-07-02 06:41:17.698         if alo < ahi:
2025-07-02 06:41:17.698             if blo < bhi:
2025-07-02 06:41:17.698                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.698             else:
2025-07-02 06:41:17.698                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.698         elif blo < bhi:
2025-07-02 06:41:17.698             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.698
2025-07-02 06:41:17.698 >       yield from g
2025-07-02 06:41:17.698
2025-07-02 06:41:17.698 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.698 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.698
2025-07-02 06:41:17.698 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.698 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.698 alo = 274, ahi = 1101
2025-07-02 06:41:17.698 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.698 blo = 274, bhi = 1101
2025-07-02 06:41:17.698
2025-07-02 06:41:17.699     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.699         r"""
2025-07-02 06:41:17.699         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.699         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.699         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.699         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.699
2025-07-02 06:41:17.699         Example:
2025-07-02 06:41:17.699
2025-07-02 06:41:17.699         >>> d = Differ()
2025-07-02 06:41:17.699         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.699         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.699         >>> print(''.join(results), end="")
2025-07-02 06:41:17.699         - abcDefghiJkl
2025-07-02 06:41:17.699         + abcdefGhijkl
2025-07-02 06:41:17.699         """
2025-07-02 06:41:17.699
2025-07-02 06:41:17.699         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.700         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.700         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.700         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.700         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.700
2025-07-02 06:41:17.700         # search for the pair that matches best without being identical
2025-07-02 06:41:17.700         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.700         # on junk -- unless we have to)
2025-07-02 06:41:17.700         for j in range(blo, bhi):
2025-07-02 06:41:17.700             bj = b[j]
2025-07-02 06:41:17.700             cruncher.set_seq2(bj)
2025-07-02 06:41:17.700             for i in range(alo, ahi):
2025-07-02 06:41:17.700                 ai = a[i]
2025-07-02 06:41:17.700                 if ai == bj:
2025-07-02 06:41:17.700                     if eqi is None:
2025-07-02 06:41:17.700                         eqi, eqj = i, j
2025-07-02 06:41:17.700                     continue
2025-07-02 06:41:17.700                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.700                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.701                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.701                 # compares by a factor of 3.
2025-07-02 06:41:17.701                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.701                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.701                 # of the computation is cached by cruncher
2025-07-02 06:41:17.701                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.701                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.701                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.701                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.701         if best_ratio < cutoff:
2025-07-02 06:41:17.701             # no non-identical "pretty close" pair
2025-07-02 06:41:17.701             if eqi is None:
2025-07-02 06:41:17.701                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.701                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.701                 return
2025-07-02 06:41:17.701             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.701             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.701         else:
2025-07-02 06:41:17.701             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.702             eqi = None
2025-07-02 06:41:17.702
2025-07-02 06:41:17.702         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.702         # identical
2025-07-02 06:41:17.702
2025-07-02 06:41:17.702         # pump out diffs from before the synch point
2025-07-02 06:41:17.702         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.702
2025-07-02 06:41:17.702         # do intraline marking on the synch pair
2025-07-02 06:41:17.702         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.702         if eqi is None:
2025-07-02 06:41:17.702             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.702             atags = btags = ""
2025-07-02 06:41:17.702             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.702             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.702                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.702                 if tag == 'replace':
2025-07-02 06:41:17.702                     atags += '^' * la
2025-07-02 06:41:17.702                     btags += '^' * lb
2025-07-02 06:41:17.703                 elif tag == 'delete':
2025-07-02 06:41:17.703                     atags += '-' * la
2025-07-02 06:41:17.703                 elif tag == 'insert':
2025-07-02 06:41:17.703                     btags += '+' * lb
2025-07-02 06:41:17.703                 elif tag == 'equal':
2025-07-02 06:41:17.703                     atags += ' ' * la
2025-07-02 06:41:17.703                     btags += ' ' * lb
2025-07-02 06:41:17.703                 else:
2025-07-02 06:41:17.703                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.703             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.703         else:
2025-07-02 06:41:17.703             # the synch pair is identical
2025-07-02 06:41:17.703             yield '  ' + aelt
2025-07-02 06:41:17.703
2025-07-02 06:41:17.703         # pump out diffs from after the synch point
2025-07-02 06:41:17.703 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.703
2025-07-02 06:41:17.703 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.703 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.703
2025-07-02 06:41:17.703 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.704 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.704 alo = 275, ahi = 1101
2025-07-02 06:41:17.704 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.704 blo = 275, bhi = 1101
2025-07-02 06:41:17.704
2025-07-02 06:41:17.704     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.704         g = []
2025-07-02 06:41:17.704         if alo < ahi:
2025-07-02 06:41:17.704             if blo < bhi:
2025-07-02 06:41:17.704                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.704             else:
2025-07-02 06:41:17.704                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.704         elif blo < bhi:
2025-07-02 06:41:17.704             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.704
2025-07-02 06:41:17.704 >       yield from g
2025-07-02 06:41:17.704
2025-07-02 06:41:17.704 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.704 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.704
2025-07-02 06:41:17.705 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.705 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.705 alo = 275, ahi = 1101
2025-07-02 06:41:17.705 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.705 blo = 275, bhi = 1101
2025-07-02 06:41:17.705
2025-07-02 06:41:17.705     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.705         r"""
2025-07-02 06:41:17.705         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.705         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.705         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.705         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.705
2025-07-02 06:41:17.705         Example:
2025-07-02 06:41:17.705
2025-07-02 06:41:17.705         >>> d = Differ()
2025-07-02 06:41:17.705         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.705         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.705         >>> print(''.join(results), end="")
2025-07-02 06:41:17.705         - abcDefghiJkl
2025-07-02 06:41:17.706         + abcdefGhijkl
2025-07-02 06:41:17.706         """
2025-07-02 06:41:17.706
2025-07-02 06:41:17.706         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.706         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.706         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.706         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.706         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.706
2025-07-02 06:41:17.706         # search for the pair that matches best without being identical
2025-07-02 06:41:17.706         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.706         # on junk -- unless we have to)
2025-07-02 06:41:17.706         for j in range(blo, bhi):
2025-07-02 06:41:17.706             bj = b[j]
2025-07-02 06:41:17.706             cruncher.set_seq2(bj)
2025-07-02 06:41:17.706             for i in range(alo, ahi):
2025-07-02 06:41:17.706                 ai = a[i]
2025-07-02 06:41:17.706                 if ai == bj:
2025-07-02 06:41:17.707                     if eqi is None:
2025-07-02 06:41:17.707                         eqi, eqj = i, j
2025-07-02 06:41:17.707                     continue
2025-07-02 06:41:17.707                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.707                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.707                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.707                 # compares by a factor of 3.
2025-07-02 06:41:17.707                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.707                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.707                 # of the computation is cached by cruncher
2025-07-02 06:41:17.707                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.707                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.707                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.707                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.707         if best_ratio < cutoff:
2025-07-02 06:41:17.707             # no non-identical "pretty close" pair
2025-07-02 06:41:17.707             if eqi is None:
2025-07-02 06:41:17.707                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.708                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.708                 return
2025-07-02 06:41:17.708             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.708             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.708         else:
2025-07-02 06:41:17.708             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.708             eqi = None
2025-07-02 06:41:17.708
2025-07-02 06:41:17.708         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.708         # identical
2025-07-02 06:41:17.708
2025-07-02 06:41:17.708         # pump out diffs from before the synch point
2025-07-02 06:41:17.708         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.708
2025-07-02 06:41:17.708         # do intraline marking on the synch pair
2025-07-02 06:41:17.708         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.708         if eqi is None:
2025-07-02 06:41:17.708             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.708             atags = btags = ""
2025-07-02 06:41:17.708             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.709             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.709                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.709                 if tag == 'replace':
2025-07-02 06:41:17.709                     atags += '^' * la
2025-07-02 06:41:17.709                     btags += '^' * lb
2025-07-02 06:41:17.709                 elif tag == 'delete':
2025-07-02 06:41:17.709                     atags += '-' * la
2025-07-02 06:41:17.709                 elif tag == 'insert':
2025-07-02 06:41:17.709                     btags += '+' * lb
2025-07-02 06:41:17.709                 elif tag == 'equal':
2025-07-02 06:41:17.709                     atags += ' ' * la
2025-07-02 06:41:17.709                     btags += ' ' * lb
2025-07-02 06:41:17.709                 else:
2025-07-02 06:41:17.709                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.709             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.709         else:
2025-07-02 06:41:17.709             # the synch pair is identical
2025-07-02 06:41:17.710             yield '  ' + aelt
2025-07-02 06:41:17.710
2025-07-02 06:41:17.710         # pump out diffs from after the synch point
2025-07-02 06:41:17.710 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.710
2025-07-02 06:41:17.710 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.710 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.710
2025-07-02 06:41:17.710 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.710 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.710 alo = 276, ahi = 1101
2025-07-02 06:41:17.710 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.710 blo = 276, bhi = 1101
2025-07-02 06:41:17.710
2025-07-02 06:41:17.710     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.710         g = []
2025-07-02 06:41:17.710         if alo < ahi:
2025-07-02 06:41:17.710             if blo < bhi:
2025-07-02 06:41:17.710                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.711             else:
2025-07-02 06:41:17.711                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.711         elif blo < bhi:
2025-07-02 06:41:17.711             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.711
2025-07-02 06:41:17.711 >       yield from g
2025-07-02 06:41:17.711
2025-07-02 06:41:17.711 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.711 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.711
2025-07-02 06:41:17.711 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.711 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.711 alo = 276, ahi = 1101
2025-07-02 06:41:17.711 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.711 blo = 276, bhi = 1101
2025-07-02 06:41:17.711
2025-07-02 06:41:17.711     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.711         r"""
2025-07-02 06:41:17.711         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.711         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.712         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.712         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.712
2025-07-02 06:41:17.712         Example:
2025-07-02 06:41:17.712
2025-07-02 06:41:17.712         >>> d = Differ()
2025-07-02 06:41:17.712         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.712         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.712         >>> print(''.join(results), end="")
2025-07-02 06:41:17.712         - abcDefghiJkl
2025-07-02 06:41:17.712         + abcdefGhijkl
2025-07-02 06:41:17.712         """
2025-07-02 06:41:17.712
2025-07-02 06:41:17.712         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.712         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.712         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.712         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.712         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.713
2025-07-02 06:41:17.713         # search for the pair that matches best without being identical
2025-07-02 06:41:17.713         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.713         # on junk -- unless we have to)
2025-07-02 06:41:17.713         for j in range(blo, bhi):
2025-07-02 06:41:17.713             bj = b[j]
2025-07-02 06:41:17.713             cruncher.set_seq2(bj)
2025-07-02 06:41:17.713             for i in range(alo, ahi):
2025-07-02 06:41:17.713                 ai = a[i]
2025-07-02 06:41:17.713                 if ai == bj:
2025-07-02 06:41:17.713                     if eqi is None:
2025-07-02 06:41:17.713                         eqi, eqj = i, j
2025-07-02 06:41:17.713                     continue
2025-07-02 06:41:17.713                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.713                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.713                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.713                 # compares by a factor of 3.
2025-07-02 06:41:17.713                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.713                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.713                 # of the computation is cached by cruncher
2025-07-02 06:41:17.714                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.714                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.714                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.714                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.714         if best_ratio < cutoff:
2025-07-02 06:41:17.714             # no non-identical "pretty close" pair
2025-07-02 06:41:17.714             if eqi is None:
2025-07-02 06:41:17.714                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.714                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.714                 return
2025-07-02 06:41:17.714             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.714             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.714         else:
2025-07-02 06:41:17.714             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.714             eqi = None
2025-07-02 06:41:17.714
2025-07-02 06:41:17.714         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.714         # identical
2025-07-02 06:41:17.714
2025-07-02 06:41:17.714         # pump out diffs from before the synch point
2025-07-02 06:41:17.715         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.715
2025-07-02 06:41:17.715         # do intraline marking on the synch pair
2025-07-02 06:41:17.715         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.715         if eqi is None:
2025-07-02 06:41:17.715             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.715             atags = btags = ""
2025-07-02 06:41:17.715             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.715             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.715                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.715                 if tag == 'replace':
2025-07-02 06:41:17.715                     atags += '^' * la
2025-07-02 06:41:17.715                     btags += '^' * lb
2025-07-02 06:41:17.715                 elif tag == 'delete':
2025-07-02 06:41:17.715                     atags += '-' * la
2025-07-02 06:41:17.715                 elif tag == 'insert':
2025-07-02 06:41:17.715                     btags += '+' * lb
2025-07-02 06:41:17.715                 elif tag == 'equal':
2025-07-02 06:41:17.715                     atags += ' ' * la
2025-07-02 06:41:17.715                     btags += ' ' * lb
2025-07-02 06:41:17.716                 else:
2025-07-02 06:41:17.716                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.716             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.716         else:
2025-07-02 06:41:17.716             # the synch pair is identical
2025-07-02 06:41:17.716             yield '  ' + aelt
2025-07-02 06:41:17.716
2025-07-02 06:41:17.716         # pump out diffs from after the synch point
2025-07-02 06:41:17.716 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.716
2025-07-02 06:41:17.716 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.716 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.716
2025-07-02 06:41:17.716 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.716 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.716 alo = 277, ahi = 1101
2025-07-02 06:41:17.716 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.717 blo = 277, bhi = 1101
2025-07-02 06:41:17.717
2025-07-02 06:41:17.717     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.717         g = []
2025-07-02 06:41:17.717         if alo < ahi:
2025-07-02 06:41:17.717             if blo < bhi:
2025-07-02 06:41:17.717                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.717             else:
2025-07-02 06:41:17.717                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.717         elif blo < bhi:
2025-07-02 06:41:17.717             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.717
2025-07-02 06:41:17.717 >       yield from g
2025-07-02 06:41:17.717
2025-07-02 06:41:17.717 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.717 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.717
2025-07-02 06:41:17.717 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.717 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.718 alo = 277, ahi = 1101
2025-07-02 06:41:17.718 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.718 blo = 277, bhi = 1101
2025-07-02 06:41:17.718
2025-07-02 06:41:17.718     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.718         r"""
2025-07-02 06:41:17.718         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.718         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.718         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.718         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.718
2025-07-02 06:41:17.718         Example:
2025-07-02 06:41:17.718
2025-07-02 06:41:17.718         >>> d = Differ()
2025-07-02 06:41:17.718         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.718         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.718         >>> print(''.join(results), end="")
2025-07-02 06:41:17.719         - abcDefghiJkl
2025-07-02 06:41:17.719         + abcdefGhijkl
2025-07-02 06:41:17.719         """
2025-07-02 06:41:17.719
2025-07-02 06:41:17.719         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.719         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.719         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.719         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.719         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.719
2025-07-02 06:41:17.719         # search for the pair that matches best without being identical
2025-07-02 06:41:17.719         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.719         # on junk -- unless we have to)
2025-07-02 06:41:17.719         for j in range(blo, bhi):
2025-07-02 06:41:17.719             bj = b[j]
2025-07-02 06:41:17.719             cruncher.set_seq2(bj)
2025-07-02 06:41:17.719             for i in range(alo, ahi):
2025-07-02 06:41:17.719                 ai = a[i]
2025-07-02 06:41:17.720                 if ai == bj:
2025-07-02 06:41:17.720                     if eqi is None:
2025-07-02 06:41:17.720                         eqi, eqj = i, j
2025-07-02 06:41:17.720                     continue
2025-07-02 06:41:17.720                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.720                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.720                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.720                 # compares by a factor of 3.
2025-07-02 06:41:17.720                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.720                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.720                 # of the computation is cached by cruncher
2025-07-02 06:41:17.720                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.720                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.720                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.720                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.720         if best_ratio < cutoff:
2025-07-02 06:41:17.720             # no non-identical "pretty close" pair
2025-07-02 06:41:17.720             if eqi is None:
2025-07-02 06:41:17.720                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.720                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.721                 return
2025-07-02 06:41:17.721             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.721             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.721         else:
2025-07-02 06:41:17.721             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.721             eqi = None
2025-07-02 06:41:17.721
2025-07-02 06:41:17.721         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.721         # identical
2025-07-02 06:41:17.721
2025-07-02 06:41:17.721         # pump out diffs from before the synch point
2025-07-02 06:41:17.721         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.721
2025-07-02 06:41:17.721         # do intraline marking on the synch pair
2025-07-02 06:41:17.721         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.721         if eqi is None:
2025-07-02 06:41:17.721             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.721             atags = btags = ""
2025-07-02 06:41:17.722             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.722             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.722                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.722                 if tag == 'replace':
2025-07-02 06:41:17.722                     atags += '^' * la
2025-07-02 06:41:17.722                     btags += '^' * lb
2025-07-02 06:41:17.722                 elif tag == 'delete':
2025-07-02 06:41:17.722                     atags += '-' * la
2025-07-02 06:41:17.722                 elif tag == 'insert':
2025-07-02 06:41:17.722                     btags += '+' * lb
2025-07-02 06:41:17.722                 elif tag == 'equal':
2025-07-02 06:41:17.722                     atags += ' ' * la
2025-07-02 06:41:17.722                     btags += ' ' * lb
2025-07-02 06:41:17.722                 else:
2025-07-02 06:41:17.722                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.722             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.722         else:
2025-07-02 06:41:17.722             # the synch pair is identical
2025-07-02 06:41:17.722             yield '  ' + aelt
2025-07-02 06:41:17.722
2025-07-02 06:41:17.723         # pump out diffs from after the synch point
2025-07-02 06:41:17.723 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.723
2025-07-02 06:41:17.723 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.723 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.723
2025-07-02 06:41:17.723 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.723 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.723 alo = 278, ahi = 1101
2025-07-02 06:41:17.723 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.723 blo = 278, bhi = 1101
2025-07-02 06:41:17.723
2025-07-02 06:41:17.723     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.723         g = []
2025-07-02 06:41:17.723         if alo < ahi:
2025-07-02 06:41:17.723             if blo < bhi:
2025-07-02 06:41:17.723                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.723             else:
2025-07-02 06:41:17.723                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.723         elif blo < bhi:
2025-07-02 06:41:17.724             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.724
2025-07-02 06:41:17.724 >       yield from g
2025-07-02 06:41:17.724
2025-07-02 06:41:17.724 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.724 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.724
2025-07-02 06:41:17.724 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.724 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.724 alo = 278, ahi = 1101
2025-07-02 06:41:17.724 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.724 blo = 278, bhi = 1101
2025-07-02 06:41:17.724
2025-07-02 06:41:17.724     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.724         r"""
2025-07-02 06:41:17.724         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.724         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.724         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.724         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.724
2025-07-02 06:41:17.725         Example:
2025-07-02 06:41:17.725
2025-07-02 06:41:17.725         >>> d = Differ()
2025-07-02 06:41:17.725         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.725         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.725         >>> print(''.join(results), end="")
2025-07-02 06:41:17.725         - abcDefghiJkl
2025-07-02 06:41:17.725         + abcdefGhijkl
2025-07-02 06:41:17.725         """
2025-07-02 06:41:17.725
2025-07-02 06:41:17.725         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.725         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.725         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.725         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.725         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.725
2025-07-02 06:41:17.726         # search for the pair that matches best without being identical
2025-07-02 06:41:17.726         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.726         # on junk -- unless we have to)
2025-07-02 06:41:17.726         for j in range(blo, bhi):
2025-07-02 06:41:17.726             bj = b[j]
2025-07-02 06:41:17.726             cruncher.set_seq2(bj)
2025-07-02 06:41:17.726             for i in range(alo, ahi):
2025-07-02 06:41:17.726                 ai = a[i]
2025-07-02 06:41:17.726                 if ai == bj:
2025-07-02 06:41:17.726                     if eqi is None:
2025-07-02 06:41:17.726                         eqi, eqj = i, j
2025-07-02 06:41:17.726                     continue
2025-07-02 06:41:17.726                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.726                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.726                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.726                 # compares by a factor of 3.
2025-07-02 06:41:17.726                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.726                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.726                 # of the computation is cached by cruncher
2025-07-02 06:41:17.726                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.727                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.727                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.727                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.727         if best_ratio < cutoff:
2025-07-02 06:41:17.727             # no non-identical "pretty close" pair
2025-07-02 06:41:17.727             if eqi is None:
2025-07-02 06:41:17.727                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.727                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.727                 return
2025-07-02 06:41:17.727             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.727             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.727         else:
2025-07-02 06:41:17.727             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.727             eqi = None
2025-07-02 06:41:17.727
2025-07-02 06:41:17.727         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.727         # identical
2025-07-02 06:41:17.727
2025-07-02 06:41:17.728         # pump out diffs from before the synch point
2025-07-02 06:41:17.728         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.728
2025-07-02 06:41:17.728         # do intraline marking on the synch pair
2025-07-02 06:41:17.728         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.728         if eqi is None:
2025-07-02 06:41:17.728             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.728             atags = btags = ""
2025-07-02 06:41:17.728             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.728             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.728                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.728                 if tag == 'replace':
2025-07-02 06:41:17.728                     atags += '^' * la
2025-07-02 06:41:17.728                     btags += '^' * lb
2025-07-02 06:41:17.728                 elif tag == 'delete':
2025-07-02 06:41:17.728                     atags += '-' * la
2025-07-02 06:41:17.728                 elif tag == 'insert':
2025-07-02 06:41:17.728                     btags += '+' * lb
2025-07-02 06:41:17.728                 elif tag == 'equal':
2025-07-02 06:41:17.729                     atags += ' ' * la
2025-07-02 06:41:17.729                     btags += ' ' * lb
2025-07-02 06:41:17.729                 else:
2025-07-02 06:41:17.729                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.729             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.729         else:
2025-07-02 06:41:17.729             # the synch pair is identical
2025-07-02 06:41:17.729             yield '  ' + aelt
2025-07-02 06:41:17.729
2025-07-02 06:41:17.729         # pump out diffs from after the synch point
2025-07-02 06:41:17.729 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.729
2025-07-02 06:41:17.729 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.729 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.729
2025-07-02 06:41:17.729 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.729 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.729 alo = 279, ahi = 1101
2025-07-02 06:41:17.729 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.729 blo = 279, bhi = 1101
2025-07-02 06:41:17.730
2025-07-02 06:41:17.730     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.730         g = []
2025-07-02 06:41:17.730         if alo < ahi:
2025-07-02 06:41:17.730             if blo < bhi:
2025-07-02 06:41:17.730                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.730             else:
2025-07-02 06:41:17.730                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.730         elif blo < bhi:
2025-07-02 06:41:17.730             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.730
2025-07-02 06:41:17.730 >       yield from g
2025-07-02 06:41:17.730
2025-07-02 06:41:17.730 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.730 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.730
2025-07-02 06:41:17.730 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.730 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.730 alo = 279, ahi = 1101
2025-07-02 06:41:17.730 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.731 blo = 279, bhi = 1101
2025-07-02 06:41:17.731
2025-07-02 06:41:17.731     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.731         r"""
2025-07-02 06:41:17.731         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.731         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.731         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.731         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.731
2025-07-02 06:41:17.731         Example:
2025-07-02 06:41:17.731
2025-07-02 06:41:17.731         >>> d = Differ()
2025-07-02 06:41:17.731         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.731         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.731         >>> print(''.join(results), end="")
2025-07-02 06:41:17.731         - abcDefghiJkl
2025-07-02 06:41:17.731         + abcdefGhijkl
2025-07-02 06:41:17.731         """
2025-07-02 06:41:17.732
2025-07-02 06:41:17.732         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.732         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.732         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.732         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.732         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.732
2025-07-02 06:41:17.732         # search for the pair that matches best without being identical
2025-07-02 06:41:17.732         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.732         # on junk -- unless we have to)
2025-07-02 06:41:17.732         for j in range(blo, bhi):
2025-07-02 06:41:17.732             bj = b[j]
2025-07-02 06:41:17.732             cruncher.set_seq2(bj)
2025-07-02 06:41:17.732             for i in range(alo, ahi):
2025-07-02 06:41:17.732                 ai = a[i]
2025-07-02 06:41:17.732                 if ai == bj:
2025-07-02 06:41:17.732                     if eqi is None:
2025-07-02 06:41:17.732                         eqi, eqj = i, j
2025-07-02 06:41:17.732                     continue
2025-07-02 06:41:17.732                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.732                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.733                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.733                 # compares by a factor of 3.
2025-07-02 06:41:17.733                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.733                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.733                 # of the computation is cached by cruncher
2025-07-02 06:41:17.733                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.733                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.733                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.733                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.733         if best_ratio < cutoff:
2025-07-02 06:41:17.733             # no non-identical "pretty close" pair
2025-07-02 06:41:17.733             if eqi is None:
2025-07-02 06:41:17.733                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.733                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.733                 return
2025-07-02 06:41:17.733             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.733             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.733         else:
2025-07-02 06:41:17.733             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.733             eqi = None
2025-07-02 06:41:17.734
2025-07-02 06:41:17.734         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.734         # identical
2025-07-02 06:41:17.734
2025-07-02 06:41:17.734         # pump out diffs from before the synch point
2025-07-02 06:41:17.734         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.734
2025-07-02 06:41:17.734         # do intraline marking on the synch pair
2025-07-02 06:41:17.734         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.734         if eqi is None:
2025-07-02 06:41:17.734             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.734             atags = btags = ""
2025-07-02 06:41:17.734             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.734             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.734                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.734                 if tag == 'replace':
2025-07-02 06:41:17.734                     atags += '^' * la
2025-07-02 06:41:17.734                     btags += '^' * lb
2025-07-02 06:41:17.734                 elif tag == 'delete':
2025-07-02 06:41:17.734                     atags += '-' * la
2025-07-02 06:41:17.735                 elif tag == 'insert':
2025-07-02 06:41:17.735                     btags += '+' * lb
2025-07-02 06:41:17.735                 elif tag == 'equal':
2025-07-02 06:41:17.735                     atags += ' ' * la
2025-07-02 06:41:17.735                     btags += ' ' * lb
2025-07-02 06:41:17.735                 else:
2025-07-02 06:41:17.735                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.735             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.735         else:
2025-07-02 06:41:17.735             # the synch pair is identical
2025-07-02 06:41:17.735             yield '  ' + aelt
2025-07-02 06:41:17.735
2025-07-02 06:41:17.735         # pump out diffs from after the synch point
2025-07-02 06:41:17.735 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.735
2025-07-02 06:41:17.735 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.735 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.735
2025-07-02 06:41:17.735 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.735 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.736 alo = 280, ahi = 1101
2025-07-02 06:41:17.736 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.736 blo = 280, bhi = 1101
2025-07-02 06:41:17.736
2025-07-02 06:41:17.736     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.736         g = []
2025-07-02 06:41:17.736         if alo < ahi:
2025-07-02 06:41:17.736             if blo < bhi:
2025-07-02 06:41:17.736                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.736             else:
2025-07-02 06:41:17.736                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.736         elif blo < bhi:
2025-07-02 06:41:17.736             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.736
2025-07-02 06:41:17.736 >       yield from g
2025-07-02 06:41:17.736
2025-07-02 06:41:17.736 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.736 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.737
2025-07-02 06:41:17.737 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.737 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.737 alo = 280, ahi = 1101
2025-07-02 06:41:17.737 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.737 blo = 280, bhi = 1101
2025-07-02 06:41:17.737
2025-07-02 06:41:17.737     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.737         r"""
2025-07-02 06:41:17.737         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.737         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.737         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.737         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.737
2025-07-02 06:41:17.737         Example:
2025-07-02 06:41:17.737
2025-07-02 06:41:17.737         >>> d = Differ()
2025-07-02 06:41:17.737         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.737         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.738         >>> print(''.join(results), end="")
2025-07-02 06:41:17.738         - abcDefghiJkl
2025-07-02 06:41:17.738         + abcdefGhijkl
2025-07-02 06:41:17.738         """
2025-07-02 06:41:17.738
2025-07-02 06:41:17.738         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.738         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.738         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.738         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.738         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.738
2025-07-02 06:41:17.738         # search for the pair that matches best without being identical
2025-07-02 06:41:17.738         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.738         # on junk -- unless we have to)
2025-07-02 06:41:17.738         for j in range(blo, bhi):
2025-07-02 06:41:17.738             bj = b[j]
2025-07-02 06:41:17.738             cruncher.set_seq2(bj)
2025-07-02 06:41:17.738             for i in range(alo, ahi):
2025-07-02 06:41:17.739                 ai = a[i]
2025-07-02 06:41:17.739                 if ai == bj:
2025-07-02 06:41:17.739                     if eqi is None:
2025-07-02 06:41:17.739                         eqi, eqj = i, j
2025-07-02 06:41:17.739                     continue
2025-07-02 06:41:17.739                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.739                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.739                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.739                 # compares by a factor of 3.
2025-07-02 06:41:17.739                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.739                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.739                 # of the computation is cached by cruncher
2025-07-02 06:41:17.739                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.739                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.739                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.739                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.739         if best_ratio < cutoff:
2025-07-02 06:41:17.739             # no non-identical "pretty close" pair
2025-07-02 06:41:17.739             if eqi is None:
2025-07-02 06:41:17.739                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.739                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.740                 return
2025-07-02 06:41:17.740             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.740             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.740         else:
2025-07-02 06:41:17.740             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.740             eqi = None
2025-07-02 06:41:17.740
2025-07-02 06:41:17.740         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.740         # identical
2025-07-02 06:41:17.740
2025-07-02 06:41:17.740         # pump out diffs from before the synch point
2025-07-02 06:41:17.740         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.740
2025-07-02 06:41:17.740         # do intraline marking on the synch pair
2025-07-02 06:41:17.740         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.740         if eqi is None:
2025-07-02 06:41:17.740             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.740             atags = btags = ""
2025-07-02 06:41:17.740             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.740             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.741                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.741                 if tag == 'replace':
2025-07-02 06:41:17.741                     atags += '^' * la
2025-07-02 06:41:17.741                     btags += '^' * lb
2025-07-02 06:41:17.741                 elif tag == 'delete':
2025-07-02 06:41:17.741                     atags += '-' * la
2025-07-02 06:41:17.741                 elif tag == 'insert':
2025-07-02 06:41:17.741                     btags += '+' * lb
2025-07-02 06:41:17.741                 elif tag == 'equal':
2025-07-02 06:41:17.741                     atags += ' ' * la
2025-07-02 06:41:17.741                     btags += ' ' * lb
2025-07-02 06:41:17.741                 else:
2025-07-02 06:41:17.741                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.741             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.741         else:
2025-07-02 06:41:17.741             # the synch pair is identical
2025-07-02 06:41:17.741             yield '  ' + aelt
2025-07-02 06:41:17.741
2025-07-02 06:41:17.742         # pump out diffs from after the synch point
2025-07-02 06:41:17.742 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.742
2025-07-02 06:41:17.742 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.742 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.742
2025-07-02 06:41:17.742 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.742 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.742 alo = 281, ahi = 1101
2025-07-02 06:41:17.742 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.742 blo = 281, bhi = 1101
2025-07-02 06:41:17.742
2025-07-02 06:41:17.742     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.742         g = []
2025-07-02 06:41:17.742         if alo < ahi:
2025-07-02 06:41:17.742             if blo < bhi:
2025-07-02 06:41:17.742                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.742             else:
2025-07-02 06:41:17.742                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.742         elif blo < bhi:
2025-07-02 06:41:17.743             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.743
2025-07-02 06:41:17.743 >       yield from g
2025-07-02 06:41:17.743
2025-07-02 06:41:17.743 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.743 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.743
2025-07-02 06:41:17.743 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.743 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.743 alo = 281, ahi = 1101
2025-07-02 06:41:17.743 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.743 blo = 281, bhi = 1101
2025-07-02 06:41:17.743
2025-07-02 06:41:17.743     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.743         r"""
2025-07-02 06:41:17.743         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.743         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.743         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.743         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.743
2025-07-02 06:41:17.744         Example:
2025-07-02 06:41:17.744
2025-07-02 06:41:17.744         >>> d = Differ()
2025-07-02 06:41:17.744         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.744         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.744         >>> print(''.join(results), end="")
2025-07-02 06:41:17.744         - abcDefghiJkl
2025-07-02 06:41:17.744         + abcdefGhijkl
2025-07-02 06:41:17.744         """
2025-07-02 06:41:17.744
2025-07-02 06:41:17.744         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.744         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.744         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.744         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.744         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.744
2025-07-02 06:41:17.745         # search for the pair that matches best without being identical
2025-07-02 06:41:17.745         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.745         # on junk -- unless we have to)
2025-07-02 06:41:17.745         for j in range(blo, bhi):
2025-07-02 06:41:17.745             bj = b[j]
2025-07-02 06:41:17.745             cruncher.set_seq2(bj)
2025-07-02 06:41:17.745             for i in range(alo, ahi):
2025-07-02 06:41:17.745                 ai = a[i]
2025-07-02 06:41:17.745                 if ai == bj:
2025-07-02 06:41:17.745                     if eqi is None:
2025-07-02 06:41:17.745                         eqi, eqj = i, j
2025-07-02 06:41:17.745                     continue
2025-07-02 06:41:17.745                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.745                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.745                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.745                 # compares by a factor of 3.
2025-07-02 06:41:17.745                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.745                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.745                 # of the computation is cached by cruncher
2025-07-02 06:41:17.745                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.746                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.746                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.746                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.746         if best_ratio < cutoff:
2025-07-02 06:41:17.746             # no non-identical "pretty close" pair
2025-07-02 06:41:17.746             if eqi is None:
2025-07-02 06:41:17.746                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.746                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.746                 return
2025-07-02 06:41:17.746             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.746             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.746         else:
2025-07-02 06:41:17.746             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.746             eqi = None
2025-07-02 06:41:17.746
2025-07-02 06:41:17.746         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.746         # identical
2025-07-02 06:41:17.746
2025-07-02 06:41:17.746         # pump out diffs from before the synch point
2025-07-02 06:41:17.747         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.747
2025-07-02 06:41:17.747         # do intraline marking on the synch pair
2025-07-02 06:41:17.747         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.747         if eqi is None:
2025-07-02 06:41:17.747             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.747             atags = btags = ""
2025-07-02 06:41:17.747             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.747             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.747                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.747                 if tag == 'replace':
2025-07-02 06:41:17.747                     atags += '^' * la
2025-07-02 06:41:17.747                     btags += '^' * lb
2025-07-02 06:41:17.747                 elif tag == 'delete':
2025-07-02 06:41:17.747                     atags += '-' * la
2025-07-02 06:41:17.747                 elif tag == 'insert':
2025-07-02 06:41:17.747                     btags += '+' * lb
2025-07-02 06:41:17.747                 elif tag == 'equal':
2025-07-02 06:41:17.747                     atags += ' ' * la
2025-07-02 06:41:17.747                     btags += ' ' * lb
2025-07-02 06:41:17.747                 else:
2025-07-02 06:41:17.748                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.748             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.748         else:
2025-07-02 06:41:17.748             # the synch pair is identical
2025-07-02 06:41:17.748             yield '  ' + aelt
2025-07-02 06:41:17.748
2025-07-02 06:41:17.748         # pump out diffs from after the synch point
2025-07-02 06:41:17.748 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.748
2025-07-02 06:41:17.748 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.748 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.748
2025-07-02 06:41:17.748 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.748 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.748 alo = 282, ahi = 1101
2025-07-02 06:41:17.748 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.748 blo = 282, bhi = 1101
2025-07-02 06:41:17.748
2025-07-02 06:41:17.748     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.748         g = []
2025-07-02 06:41:17.749         if alo < ahi:
2025-07-02 06:41:17.749             if blo < bhi:
2025-07-02 06:41:17.749                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.749             else:
2025-07-02 06:41:17.749                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.749         elif blo < bhi:
2025-07-02 06:41:17.749             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.749
2025-07-02 06:41:17.749 >       yield from g
2025-07-02 06:41:17.749
2025-07-02 06:41:17.749 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.749 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.749
2025-07-02 06:41:17.749 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.749 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.749 alo = 282, ahi = 1101
2025-07-02 06:41:17.749 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.749 blo = 282, bhi = 1101
2025-07-02 06:41:17.749
2025-07-02 06:41:17.749     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.750         r"""
2025-07-02 06:41:17.750         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.750         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.750         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.750         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.750
2025-07-02 06:41:17.750         Example:
2025-07-02 06:41:17.750
2025-07-02 06:41:17.750         >>> d = Differ()
2025-07-02 06:41:17.750         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.750         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.750         >>> print(''.join(results), end="")
2025-07-02 06:41:17.750         - abcDefghiJkl
2025-07-02 06:41:17.750         + abcdefGhijkl
2025-07-02 06:41:17.750         """
2025-07-02 06:41:17.750
2025-07-02 06:41:17.750         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.750         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.751         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.751         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.751         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.751
2025-07-02 06:41:17.751         # search for the pair that matches best without being identical
2025-07-02 06:41:17.751         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.751         # on junk -- unless we have to)
2025-07-02 06:41:17.751         for j in range(blo, bhi):
2025-07-02 06:41:17.751             bj = b[j]
2025-07-02 06:41:17.751             cruncher.set_seq2(bj)
2025-07-02 06:41:17.751             for i in range(alo, ahi):
2025-07-02 06:41:17.751                 ai = a[i]
2025-07-02 06:41:17.751                 if ai == bj:
2025-07-02 06:41:17.751                     if eqi is None:
2025-07-02 06:41:17.751                         eqi, eqj = i, j
2025-07-02 06:41:17.751                     continue
2025-07-02 06:41:17.751                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.751                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.751                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.751                 # compares by a factor of 3.
2025-07-02 06:41:17.751                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.752                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.752                 # of the computation is cached by cruncher
2025-07-02 06:41:17.752                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.752                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.752                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.752                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.752         if best_ratio < cutoff:
2025-07-02 06:41:17.752             # no non-identical "pretty close" pair
2025-07-02 06:41:17.752             if eqi is None:
2025-07-02 06:41:17.752                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.752                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.752                 return
2025-07-02 06:41:17.752             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.752             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.752         else:
2025-07-02 06:41:17.752             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.752             eqi = None
2025-07-02 06:41:17.752
2025-07-02 06:41:17.752         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.752         # identical
2025-07-02 06:41:17.753
2025-07-02 06:41:17.753         # pump out diffs from before the synch point
2025-07-02 06:41:17.753         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.753
2025-07-02 06:41:17.753         # do intraline marking on the synch pair
2025-07-02 06:41:17.753         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.753         if eqi is None:
2025-07-02 06:41:17.753             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.753             atags = btags = ""
2025-07-02 06:41:17.753             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.753             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.753                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.753                 if tag == 'replace':
2025-07-02 06:41:17.753                     atags += '^' * la
2025-07-02 06:41:17.753                     btags += '^' * lb
2025-07-02 06:41:17.753                 elif tag == 'delete':
2025-07-02 06:41:17.753                     atags += '-' * la
2025-07-02 06:41:17.753                 elif tag == 'insert':
2025-07-02 06:41:17.753                     btags += '+' * lb
2025-07-02 06:41:17.754                 elif tag == 'equal':
2025-07-02 06:41:17.754                     atags += ' ' * la
2025-07-02 06:41:17.754                     btags += ' ' * lb
2025-07-02 06:41:17.754                 else:
2025-07-02 06:41:17.754                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.754             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.754         else:
2025-07-02 06:41:17.754             # the synch pair is identical
2025-07-02 06:41:17.754             yield '  ' + aelt
2025-07-02 06:41:17.754
2025-07-02 06:41:17.754         # pump out diffs from after the synch point
2025-07-02 06:41:17.754 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.754
2025-07-02 06:41:17.754 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.754 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.754
2025-07-02 06:41:17.754 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.754 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.754 alo = 283, ahi = 1101
2025-07-02 06:41:17.755 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.755 blo = 283, bhi = 1101
2025-07-02 06:41:17.755
2025-07-02 06:41:17.755     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.755         g = []
2025-07-02 06:41:17.755         if alo < ahi:
2025-07-02 06:41:17.755             if blo < bhi:
2025-07-02 06:41:17.755                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.755             else:
2025-07-02 06:41:17.755                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.755         elif blo < bhi:
2025-07-02 06:41:17.755             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.755
2025-07-02 06:41:17.755 >       yield from g
2025-07-02 06:41:17.755
2025-07-02 06:41:17.755 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.755 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.755
2025-07-02 06:41:17.755 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.755 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.756 alo = 283, ahi = 1101
2025-07-02 06:41:17.756 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.756 blo = 283, bhi = 1101
2025-07-02 06:41:17.756
2025-07-02 06:41:17.756     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.756         r"""
2025-07-02 06:41:17.756         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.756         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.756         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.756         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.756
2025-07-02 06:41:17.756         Example:
2025-07-02 06:41:17.756
2025-07-02 06:41:17.756         >>> d = Differ()
2025-07-02 06:41:17.756         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.756         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.756         >>> print(''.join(results), end="")
2025-07-02 06:41:17.756         - abcDefghiJkl
2025-07-02 06:41:17.756         + abcdefGhijkl
2025-07-02 06:41:17.757         """
2025-07-02 06:41:17.757
2025-07-02 06:41:17.757         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.757         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.757         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.757         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.757         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.757
2025-07-02 06:41:17.757         # search for the pair that matches best without being identical
2025-07-02 06:41:17.757         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.757         # on junk -- unless we have to)
2025-07-02 06:41:17.757         for j in range(blo, bhi):
2025-07-02 06:41:17.757             bj = b[j]
2025-07-02 06:41:17.757             cruncher.set_seq2(bj)
2025-07-02 06:41:17.757             for i in range(alo, ahi):
2025-07-02 06:41:17.757                 ai = a[i]
2025-07-02 06:41:17.757                 if ai == bj:
2025-07-02 06:41:17.757                     if eqi is None:
2025-07-02 06:41:17.758                         eqi, eqj = i, j
2025-07-02 06:41:17.758                     continue
2025-07-02 06:41:17.758                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.758                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.758                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.758                 # compares by a factor of 3.
2025-07-02 06:41:17.758                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.758                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.758                 # of the computation is cached by cruncher
2025-07-02 06:41:17.758                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.758                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.758                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.758                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.758         if best_ratio < cutoff:
2025-07-02 06:41:17.758             # no non-identical "pretty close" pair
2025-07-02 06:41:17.758             if eqi is None:
2025-07-02 06:41:17.758                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.758                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.758                 return
2025-07-02 06:41:17.759             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.759             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.759         else:
2025-07-02 06:41:17.759             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.759             eqi = None
2025-07-02 06:41:17.759
2025-07-02 06:41:17.759         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.759         # identical
2025-07-02 06:41:17.759
2025-07-02 06:41:17.759         # pump out diffs from before the synch point
2025-07-02 06:41:17.759         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.759
2025-07-02 06:41:17.759         # do intraline marking on the synch pair
2025-07-02 06:41:17.759         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.759         if eqi is None:
2025-07-02 06:41:17.759             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.759             atags = btags = ""
2025-07-02 06:41:17.759             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.759             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.759                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.760                 if tag == 'replace':
2025-07-02 06:41:17.760                     atags += '^' * la
2025-07-02 06:41:17.760                     btags += '^' * lb
2025-07-02 06:41:17.760                 elif tag == 'delete':
2025-07-02 06:41:17.760                     atags += '-' * la
2025-07-02 06:41:17.760                 elif tag == 'insert':
2025-07-02 06:41:17.760                     btags += '+' * lb
2025-07-02 06:41:17.760                 elif tag == 'equal':
2025-07-02 06:41:17.760                     atags += ' ' * la
2025-07-02 06:41:17.760                     btags += ' ' * lb
2025-07-02 06:41:17.760                 else:
2025-07-02 06:41:17.760                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.760             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.760         else:
2025-07-02 06:41:17.760             # the synch pair is identical
2025-07-02 06:41:17.760             yield '  ' + aelt
2025-07-02 06:41:17.760
2025-07-02 06:41:17.760         # pump out diffs from after the synch point
2025-07-02 06:41:17.760 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.760
2025-07-02 06:41:17.761 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.761 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.761
2025-07-02 06:41:17.761 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.761 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.761 alo = 284, ahi = 1101
2025-07-02 06:41:17.761 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.761 blo = 284, bhi = 1101
2025-07-02 06:41:17.761
2025-07-02 06:41:17.761     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.761         g = []
2025-07-02 06:41:17.761         if alo < ahi:
2025-07-02 06:41:17.761             if blo < bhi:
2025-07-02 06:41:17.761                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.761             else:
2025-07-02 06:41:17.761                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.761         elif blo < bhi:
2025-07-02 06:41:17.761             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.761
2025-07-02 06:41:17.761 >       yield from g
2025-07-02 06:41:17.762
2025-07-02 06:41:17.762 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.762 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.762
2025-07-02 06:41:17.762 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.762 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.762 alo = 284, ahi = 1101
2025-07-02 06:41:17.762 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.762 blo = 284, bhi = 1101
2025-07-02 06:41:17.762
2025-07-02 06:41:17.762     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.762         r"""
2025-07-02 06:41:17.762         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.762         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.762         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.762         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.762
2025-07-02 06:41:17.762         Example:
2025-07-02 06:41:17.763
2025-07-02 06:41:17.763         >>> d = Differ()
2025-07-02 06:41:17.763         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.763         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.763         >>> print(''.join(results), end="")
2025-07-02 06:41:17.763         - abcDefghiJkl
2025-07-02 06:41:17.763         + abcdefGhijkl
2025-07-02 06:41:17.763         """
2025-07-02 06:41:17.763
2025-07-02 06:41:17.763         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.763         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.763         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.763         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.763         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.763
2025-07-02 06:41:17.763         # search for the pair that matches best without being identical
2025-07-02 06:41:17.763         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.764         # on junk -- unless we have to)
2025-07-02 06:41:17.764         for j in range(blo, bhi):
2025-07-02 06:41:17.764             bj = b[j]
2025-07-02 06:41:17.764             cruncher.set_seq2(bj)
2025-07-02 06:41:17.764             for i in range(alo, ahi):
2025-07-02 06:41:17.764                 ai = a[i]
2025-07-02 06:41:17.764                 if ai == bj:
2025-07-02 06:41:17.764                     if eqi is None:
2025-07-02 06:41:17.764                         eqi, eqj = i, j
2025-07-02 06:41:17.764                     continue
2025-07-02 06:41:17.764                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.764                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.764                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.764                 # compares by a factor of 3.
2025-07-02 06:41:17.764                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.764                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.764                 # of the computation is cached by cruncher
2025-07-02 06:41:17.764                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.764                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.764                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.765                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.765         if best_ratio < cutoff:
2025-07-02 06:41:17.765             # no non-identical "pretty close" pair
2025-07-02 06:41:17.765             if eqi is None:
2025-07-02 06:41:17.765                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.765                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.765                 return
2025-07-02 06:41:17.765             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.765             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.765         else:
2025-07-02 06:41:17.765             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.765             eqi = None
2025-07-02 06:41:17.765
2025-07-02 06:41:17.765         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.765         # identical
2025-07-02 06:41:17.765
2025-07-02 06:41:17.765         # pump out diffs from before the synch point
2025-07-02 06:41:17.765         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.765
2025-07-02 06:41:17.765         # do intraline marking on the synch pair
2025-07-02 06:41:17.765         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.766         if eqi is None:
2025-07-02 06:41:17.766             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.766             atags = btags = ""
2025-07-02 06:41:17.766             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.766             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.766                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.766                 if tag == 'replace':
2025-07-02 06:41:17.766                     atags += '^' * la
2025-07-02 06:41:17.766                     btags += '^' * lb
2025-07-02 06:41:17.766                 elif tag == 'delete':
2025-07-02 06:41:17.766                     atags += '-' * la
2025-07-02 06:41:17.766                 elif tag == 'insert':
2025-07-02 06:41:17.766                     btags += '+' * lb
2025-07-02 06:41:17.766                 elif tag == 'equal':
2025-07-02 06:41:17.766                     atags += ' ' * la
2025-07-02 06:41:17.766                     btags += ' ' * lb
2025-07-02 06:41:17.766                 else:
2025-07-02 06:41:17.766                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.766             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.766         else:
2025-07-02 06:41:17.767             # the synch pair is identical
2025-07-02 06:41:17.767             yield '  ' + aelt
2025-07-02 06:41:17.767
2025-07-02 06:41:17.767         # pump out diffs from after the synch point
2025-07-02 06:41:17.767 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.767
2025-07-02 06:41:17.767 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.767 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.767
2025-07-02 06:41:17.767 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.767 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.767 alo = 285, ahi = 1101
2025-07-02 06:41:17.767 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.767 blo = 285, bhi = 1101
2025-07-02 06:41:17.767
2025-07-02 06:41:17.767     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.767         g = []
2025-07-02 06:41:17.767         if alo < ahi:
2025-07-02 06:41:17.767             if blo < bhi:
2025-07-02 06:41:17.767                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.768             else:
2025-07-02 06:41:17.768                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.768         elif blo < bhi:
2025-07-02 06:41:17.768             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.768
2025-07-02 06:41:17.768 >       yield from g
2025-07-02 06:41:17.768
2025-07-02 06:41:17.768 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.768 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.768
2025-07-02 06:41:17.768 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.768 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.768 alo = 285, ahi = 1101
2025-07-02 06:41:17.768 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.768 blo = 285, bhi = 1101
2025-07-02 06:41:17.768
2025-07-02 06:41:17.768     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.768         r"""
2025-07-02 06:41:17.768         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.768         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.769         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.769         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.769
2025-07-02 06:41:17.769         Example:
2025-07-02 06:41:17.769
2025-07-02 06:41:17.769         >>> d = Differ()
2025-07-02 06:41:17.769         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.769         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.769         >>> print(''.join(results), end="")
2025-07-02 06:41:17.769         - abcDefghiJkl
2025-07-02 06:41:17.769         + abcdefGhijkl
2025-07-02 06:41:17.769         """
2025-07-02 06:41:17.769
2025-07-02 06:41:17.769         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.769         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.769         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.769         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.769         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.770
2025-07-02 06:41:17.770         # search for the pair that matches best without being identical
2025-07-02 06:41:17.770         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.770         # on junk -- unless we have to)
2025-07-02 06:41:17.770         for j in range(blo, bhi):
2025-07-02 06:41:17.770             bj = b[j]
2025-07-02 06:41:17.770             cruncher.set_seq2(bj)
2025-07-02 06:41:17.770             for i in range(alo, ahi):
2025-07-02 06:41:17.770                 ai = a[i]
2025-07-02 06:41:17.770                 if ai == bj:
2025-07-02 06:41:17.770                     if eqi is None:
2025-07-02 06:41:17.770                         eqi, eqj = i, j
2025-07-02 06:41:17.770                     continue
2025-07-02 06:41:17.770                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.770                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.770                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.770                 # compares by a factor of 3.
2025-07-02 06:41:17.770                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.770                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.771                 # of the computation is cached by cruncher
2025-07-02 06:41:17.771                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.771                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.771                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.771                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.771         if best_ratio < cutoff:
2025-07-02 06:41:17.771             # no non-identical "pretty close" pair
2025-07-02 06:41:17.771             if eqi is None:
2025-07-02 06:41:17.771                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.771                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.771                 return
2025-07-02 06:41:17.771             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.771             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.771         else:
2025-07-02 06:41:17.771             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.771             eqi = None
2025-07-02 06:41:17.771
2025-07-02 06:41:17.771         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.771         # identical
2025-07-02 06:41:17.772
2025-07-02 06:41:17.772         # pump out diffs from before the synch point
2025-07-02 06:41:17.772         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.772
2025-07-02 06:41:17.772         # do intraline marking on the synch pair
2025-07-02 06:41:17.772         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.772         if eqi is None:
2025-07-02 06:41:17.772             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.772             atags = btags = ""
2025-07-02 06:41:17.772             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.772             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.772                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.772                 if tag == 'replace':
2025-07-02 06:41:17.772                     atags += '^' * la
2025-07-02 06:41:17.772                     btags += '^' * lb
2025-07-02 06:41:17.772                 elif tag == 'delete':
2025-07-02 06:41:17.772                     atags += '-' * la
2025-07-02 06:41:17.772                 elif tag == 'insert':
2025-07-02 06:41:17.772                     btags += '+' * lb
2025-07-02 06:41:17.772                 elif tag == 'equal':
2025-07-02 06:41:17.773                     atags += ' ' * la
2025-07-02 06:41:17.773                     btags += ' ' * lb
2025-07-02 06:41:17.773                 else:
2025-07-02 06:41:17.773                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.773             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.773         else:
2025-07-02 06:41:17.773             # the synch pair is identical
2025-07-02 06:41:17.773             yield '  ' + aelt
2025-07-02 06:41:17.773
2025-07-02 06:41:17.773         # pump out diffs from after the synch point
2025-07-02 06:41:17.773 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.773
2025-07-02 06:41:17.773 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.773 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.773
2025-07-02 06:41:17.773 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.773 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.773 alo = 286, ahi = 1101
2025-07-02 06:41:17.774 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.774 blo = 286, bhi = 1101
2025-07-02 06:41:17.774
2025-07-02 06:41:17.774     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.774         g = []
2025-07-02 06:41:17.774         if alo < ahi:
2025-07-02 06:41:17.774             if blo < bhi:
2025-07-02 06:41:17.774                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.774             else:
2025-07-02 06:41:17.774                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.774         elif blo < bhi:
2025-07-02 06:41:17.774             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.774
2025-07-02 06:41:17.774 >       yield from g
2025-07-02 06:41:17.774
2025-07-02 06:41:17.774 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.774 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.774
2025-07-02 06:41:17.774 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.775 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.775 alo = 286, ahi = 1101
2025-07-02 06:41:17.775 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.775 blo = 286, bhi = 1101
2025-07-02 06:41:17.775
2025-07-02 06:41:17.775     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.775         r"""
2025-07-02 06:41:17.775         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.775         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.775         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.775         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.775
2025-07-02 06:41:17.775         Example:
2025-07-02 06:41:17.775
2025-07-02 06:41:17.775         >>> d = Differ()
2025-07-02 06:41:17.775         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.775         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.775         >>> print(''.join(results), end="")
2025-07-02 06:41:17.775         - abcDefghiJkl
2025-07-02 06:41:17.776         + abcdefGhijkl
2025-07-02 06:41:17.776         """
2025-07-02 06:41:17.776
2025-07-02 06:41:17.776         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.776         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.776         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.776         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.776         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.776
2025-07-02 06:41:17.776         # search for the pair that matches best without being identical
2025-07-02 06:41:17.776         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.776         # on junk -- unless we have to)
2025-07-02 06:41:17.776         for j in range(blo, bhi):
2025-07-02 06:41:17.776             bj = b[j]
2025-07-02 06:41:17.776             cruncher.set_seq2(bj)
2025-07-02 06:41:17.776             for i in range(alo, ahi):
2025-07-02 06:41:17.776                 ai = a[i]
2025-07-02 06:41:17.776                 if ai == bj:
2025-07-02 06:41:17.777                     if eqi is None:
2025-07-02 06:41:17.777                         eqi, eqj = i, j
2025-07-02 06:41:17.777                     continue
2025-07-02 06:41:17.777                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.777                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.777                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.777                 # compares by a factor of 3.
2025-07-02 06:41:17.777                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.777                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.777                 # of the computation is cached by cruncher
2025-07-02 06:41:17.777                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.777                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.777                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.777                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.777         if best_ratio < cutoff:
2025-07-02 06:41:17.777             # no non-identical "pretty close" pair
2025-07-02 06:41:17.777             if eqi is None:
2025-07-02 06:41:17.777                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.777                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.778                 return
2025-07-02 06:41:17.778             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.778             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.778         else:
2025-07-02 06:41:17.778             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.778             eqi = None
2025-07-02 06:41:17.778
2025-07-02 06:41:17.778         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.778         # identical
2025-07-02 06:41:17.778
2025-07-02 06:41:17.778         # pump out diffs from before the synch point
2025-07-02 06:41:17.778         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.778
2025-07-02 06:41:17.778         # do intraline marking on the synch pair
2025-07-02 06:41:17.778         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.778         if eqi is None:
2025-07-02 06:41:17.778             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.778             atags = btags = ""
2025-07-02 06:41:17.778             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.778             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.779                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.779                 if tag == 'replace':
2025-07-02 06:41:17.779                     atags += '^' * la
2025-07-02 06:41:17.779                     btags += '^' * lb
2025-07-02 06:41:17.779                 elif tag == 'delete':
2025-07-02 06:41:17.779                     atags += '-' * la
2025-07-02 06:41:17.779                 elif tag == 'insert':
2025-07-02 06:41:17.779                     btags += '+' * lb
2025-07-02 06:41:17.779                 elif tag == 'equal':
2025-07-02 06:41:17.779                     atags += ' ' * la
2025-07-02 06:41:17.779                     btags += ' ' * lb
2025-07-02 06:41:17.779                 else:
2025-07-02 06:41:17.779                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.779             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.779         else:
2025-07-02 06:41:17.779             # the synch pair is identical
2025-07-02 06:41:17.779             yield '  ' + aelt
2025-07-02 06:41:17.779
2025-07-02 06:41:17.779         # pump out diffs from after the synch point
2025-07-02 06:41:17.779 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.780
2025-07-02 06:41:17.780 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.780 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.780
2025-07-02 06:41:17.780 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.780 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.780 alo = 287, ahi = 1101
2025-07-02 06:41:17.780 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.780 blo = 287, bhi = 1101
2025-07-02 06:41:17.780
2025-07-02 06:41:17.780     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.780         g = []
2025-07-02 06:41:17.780         if alo < ahi:
2025-07-02 06:41:17.780             if blo < bhi:
2025-07-02 06:41:17.780                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.780             else:
2025-07-02 06:41:17.780                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.780         elif blo < bhi:
2025-07-02 06:41:17.780             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.781
2025-07-02 06:41:17.781 >       yield from g
2025-07-02 06:41:17.781
2025-07-02 06:41:17.781 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.781 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.781
2025-07-02 06:41:17.781 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.781 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.781 alo = 287, ahi = 1101
2025-07-02 06:41:17.781 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.781 blo = 287, bhi = 1101
2025-07-02 06:41:17.781
2025-07-02 06:41:17.781     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.781         r"""
2025-07-02 06:41:17.781         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.781         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.781         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.781         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.781
2025-07-02 06:41:17.782         Example:
2025-07-02 06:41:17.782
2025-07-02 06:41:17.782         >>> d = Differ()
2025-07-02 06:41:17.782         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.782         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.782         >>> print(''.join(results), end="")
2025-07-02 06:41:17.782         - abcDefghiJkl
2025-07-02 06:41:17.782         + abcdefGhijkl
2025-07-02 06:41:17.782         """
2025-07-02 06:41:17.782
2025-07-02 06:41:17.782         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.782         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.782         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.782         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.782         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.782
2025-07-02 06:41:17.782         # search for the pair that matches best without being identical
2025-07-02 06:41:17.782         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.783         # on junk -- unless we have to)
2025-07-02 06:41:17.783         for j in range(blo, bhi):
2025-07-02 06:41:17.783             bj = b[j]
2025-07-02 06:41:17.783             cruncher.set_seq2(bj)
2025-07-02 06:41:17.783             for i in range(alo, ahi):
2025-07-02 06:41:17.783                 ai = a[i]
2025-07-02 06:41:17.783                 if ai == bj:
2025-07-02 06:41:17.783                     if eqi is None:
2025-07-02 06:41:17.783                         eqi, eqj = i, j
2025-07-02 06:41:17.783                     continue
2025-07-02 06:41:17.783                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.783                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.783                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.783                 # compares by a factor of 3.
2025-07-02 06:41:17.783                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.783                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.783                 # of the computation is cached by cruncher
2025-07-02 06:41:17.783                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.783                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.783                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.783                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.784         if best_ratio < cutoff:
2025-07-02 06:41:17.784             # no non-identical "pretty close" pair
2025-07-02 06:41:17.784             if eqi is None:
2025-07-02 06:41:17.784                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.784                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.784                 return
2025-07-02 06:41:17.784             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.784             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.784         else:
2025-07-02 06:41:17.784             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.784             eqi = None
2025-07-02 06:41:17.784
2025-07-02 06:41:17.784         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.784         # identical
2025-07-02 06:41:17.784
2025-07-02 06:41:17.784         # pump out diffs from before the synch point
2025-07-02 06:41:17.784         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.784
2025-07-02 06:41:17.784         # do intraline marking on the synch pair
2025-07-02 06:41:17.784         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.785         if eqi is None:
2025-07-02 06:41:17.785             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.785             atags = btags = ""
2025-07-02 06:41:17.785             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.785             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.785                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.785                 if tag == 'replace':
2025-07-02 06:41:17.785                     atags += '^' * la
2025-07-02 06:41:17.785                     btags += '^' * lb
2025-07-02 06:41:17.785                 elif tag == 'delete':
2025-07-02 06:41:17.785                     atags += '-' * la
2025-07-02 06:41:17.785                 elif tag == 'insert':
2025-07-02 06:41:17.785                     btags += '+' * lb
2025-07-02 06:41:17.785                 elif tag == 'equal':
2025-07-02 06:41:17.785                     atags += ' ' * la
2025-07-02 06:41:17.785                     btags += ' ' * lb
2025-07-02 06:41:17.785                 else:
2025-07-02 06:41:17.785                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.785             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.785         else:
2025-07-02 06:41:17.786             # the synch pair is identical
2025-07-02 06:41:17.786             yield '  ' + aelt
2025-07-02 06:41:17.786
2025-07-02 06:41:17.786         # pump out diffs from after the synch point
2025-07-02 06:41:17.786 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.786
2025-07-02 06:41:17.786 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.786 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.786
2025-07-02 06:41:17.786 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.786 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.786 alo = 290, ahi = 1101
2025-07-02 06:41:17.786 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.786 blo = 290, bhi = 1101
2025-07-02 06:41:17.786
2025-07-02 06:41:17.786     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.786         g = []
2025-07-02 06:41:17.786         if alo < ahi:
2025-07-02 06:41:17.786             if blo < bhi:
2025-07-02 06:41:17.786                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.787             else:
2025-07-02 06:41:17.787                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.787         elif blo < bhi:
2025-07-02 06:41:17.787             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.787
2025-07-02 06:41:17.787 >       yield from g
2025-07-02 06:41:17.787
2025-07-02 06:41:17.787 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.787 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.787
2025-07-02 06:41:17.787 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.787 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.787 alo = 290, ahi = 1101
2025-07-02 06:41:17.787 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.787 blo = 290, bhi = 1101
2025-07-02 06:41:17.787
2025-07-02 06:41:17.787     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.787         r"""
2025-07-02 06:41:17.787         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.787         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.788         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.788         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.788
2025-07-02 06:41:17.788         Example:
2025-07-02 06:41:17.788
2025-07-02 06:41:17.788         >>> d = Differ()
2025-07-02 06:41:17.788         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.788         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.788         >>> print(''.join(results), end="")
2025-07-02 06:41:17.788         - abcDefghiJkl
2025-07-02 06:41:17.788         + abcdefGhijkl
2025-07-02 06:41:17.788         """
2025-07-02 06:41:17.788
2025-07-02 06:41:17.788         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.788         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.788         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.788         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.789         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.789
2025-07-02 06:41:17.789         # search for the pair that matches best without being identical
2025-07-02 06:41:17.789         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.789         # on junk -- unless we have to)
2025-07-02 06:41:17.789         for j in range(blo, bhi):
2025-07-02 06:41:17.789             bj = b[j]
2025-07-02 06:41:17.789             cruncher.set_seq2(bj)
2025-07-02 06:41:17.789             for i in range(alo, ahi):
2025-07-02 06:41:17.789                 ai = a[i]
2025-07-02 06:41:17.789                 if ai == bj:
2025-07-02 06:41:17.789                     if eqi is None:
2025-07-02 06:41:17.789                         eqi, eqj = i, j
2025-07-02 06:41:17.789                     continue
2025-07-02 06:41:17.789                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.789                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.789                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.789                 # compares by a factor of 3.
2025-07-02 06:41:17.789                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.790                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.790                 # of the computation is cached by cruncher
2025-07-02 06:41:17.790                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.790                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.790                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.790                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.790         if best_ratio < cutoff:
2025-07-02 06:41:17.790             # no non-identical "pretty close" pair
2025-07-02 06:41:17.790             if eqi is None:
2025-07-02 06:41:17.790                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.790                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.790                 return
2025-07-02 06:41:17.790             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.790             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.790         else:
2025-07-02 06:41:17.790             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.790             eqi = None
2025-07-02 06:41:17.790
2025-07-02 06:41:17.790         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.790         # identical
2025-07-02 06:41:17.791
2025-07-02 06:41:17.791         # pump out diffs from before the synch point
2025-07-02 06:41:17.791         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.791
2025-07-02 06:41:17.791         # do intraline marking on the synch pair
2025-07-02 06:41:17.791         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.791         if eqi is None:
2025-07-02 06:41:17.791             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.791             atags = btags = ""
2025-07-02 06:41:17.791             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.791             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.791                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.791                 if tag == 'replace':
2025-07-02 06:41:17.791                     atags += '^' * la
2025-07-02 06:41:17.791                     btags += '^' * lb
2025-07-02 06:41:17.791                 elif tag == 'delete':
2025-07-02 06:41:17.791                     atags += '-' * la
2025-07-02 06:41:17.791                 elif tag == 'insert':
2025-07-02 06:41:17.791                     btags += '+' * lb
2025-07-02 06:41:17.791                 elif tag == 'equal':
2025-07-02 06:41:17.791                     atags += ' ' * la
2025-07-02 06:41:17.792                     btags += ' ' * lb
2025-07-02 06:41:17.792                 else:
2025-07-02 06:41:17.792                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.792             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.792         else:
2025-07-02 06:41:17.792             # the synch pair is identical
2025-07-02 06:41:17.792             yield '  ' + aelt
2025-07-02 06:41:17.792
2025-07-02 06:41:17.792         # pump out diffs from after the synch point
2025-07-02 06:41:17.792 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.792
2025-07-02 06:41:17.792 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.792 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.792
2025-07-02 06:41:17.792 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.792 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.792 alo = 291, ahi = 1101
2025-07-02 06:41:17.792 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.792 blo = 291, bhi = 1101
2025-07-02 06:41:17.792
2025-07-02 06:41:17.793     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.793         g = []
2025-07-02 06:41:17.793         if alo < ahi:
2025-07-02 06:41:17.793             if blo < bhi:
2025-07-02 06:41:17.793                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.793             else:
2025-07-02 06:41:17.793                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.793         elif blo < bhi:
2025-07-02 06:41:17.793             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.793
2025-07-02 06:41:17.793 >       yield from g
2025-07-02 06:41:17.793
2025-07-02 06:41:17.793 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.793 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.793
2025-07-02 06:41:17.793 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.793 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.793 alo = 291, ahi = 1101
2025-07-02 06:41:17.793 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.793 blo = 291, bhi = 1101
2025-07-02 06:41:17.794
2025-07-02 06:41:17.794     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.794         r"""
2025-07-02 06:41:17.794         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.794         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.794         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.794         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.794
2025-07-02 06:41:17.794         Example:
2025-07-02 06:41:17.794
2025-07-02 06:41:17.794         >>> d = Differ()
2025-07-02 06:41:17.794         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.794         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.794         >>> print(''.join(results), end="")
2025-07-02 06:41:17.794         - abcDefghiJkl
2025-07-02 06:41:17.794         + abcdefGhijkl
2025-07-02 06:41:17.794         """
2025-07-02 06:41:17.794
2025-07-02 06:41:17.794         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.795         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.795         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.795         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.795         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.795
2025-07-02 06:41:17.795         # search for the pair that matches best without being identical
2025-07-02 06:41:17.795         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.795         # on junk -- unless we have to)
2025-07-02 06:41:17.795         for j in range(blo, bhi):
2025-07-02 06:41:17.795             bj = b[j]
2025-07-02 06:41:17.795             cruncher.set_seq2(bj)
2025-07-02 06:41:17.795             for i in range(alo, ahi):
2025-07-02 06:41:17.795                 ai = a[i]
2025-07-02 06:41:17.795                 if ai == bj:
2025-07-02 06:41:17.795                     if eqi is None:
2025-07-02 06:41:17.795                         eqi, eqj = i, j
2025-07-02 06:41:17.795                     continue
2025-07-02 06:41:17.795                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.795                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.795                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.796                 # compares by a factor of 3.
2025-07-02 06:41:17.796                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.796                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.796                 # of the computation is cached by cruncher
2025-07-02 06:41:17.796                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.796                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.796                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.796                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.796         if best_ratio < cutoff:
2025-07-02 06:41:17.796             # no non-identical "pretty close" pair
2025-07-02 06:41:17.796             if eqi is None:
2025-07-02 06:41:17.796                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.796                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.796                 return
2025-07-02 06:41:17.796             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.796             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.796         else:
2025-07-02 06:41:17.796             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.796             eqi = None
2025-07-02 06:41:17.797
2025-07-02 06:41:17.797         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.797         # identical
2025-07-02 06:41:17.797
2025-07-02 06:41:17.797         # pump out diffs from before the synch point
2025-07-02 06:41:17.797         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.797
2025-07-02 06:41:17.797         # do intraline marking on the synch pair
2025-07-02 06:41:17.797         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.797         if eqi is None:
2025-07-02 06:41:17.797             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.797             atags = btags = ""
2025-07-02 06:41:17.797             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.797             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.797                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.797                 if tag == 'replace':
2025-07-02 06:41:17.797                     atags += '^' * la
2025-07-02 06:41:17.797                     btags += '^' * lb
2025-07-02 06:41:17.797                 elif tag == 'delete':
2025-07-02 06:41:17.797                     atags += '-' * la
2025-07-02 06:41:17.798                 elif tag == 'insert':
2025-07-02 06:41:17.798                     btags += '+' * lb
2025-07-02 06:41:17.798                 elif tag == 'equal':
2025-07-02 06:41:17.798                     atags += ' ' * la
2025-07-02 06:41:17.798                     btags += ' ' * lb
2025-07-02 06:41:17.798                 else:
2025-07-02 06:41:17.798                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.798             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.798         else:
2025-07-02 06:41:17.798             # the synch pair is identical
2025-07-02 06:41:17.798             yield '  ' + aelt
2025-07-02 06:41:17.798
2025-07-02 06:41:17.798         # pump out diffs from after the synch point
2025-07-02 06:41:17.798 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.798
2025-07-02 06:41:17.798 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.798 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.798
2025-07-02 06:41:17.798 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.799 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.799 alo = 292, ahi = 1101
2025-07-02 06:41:17.799 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.799 blo = 292, bhi = 1101
2025-07-02 06:41:17.799
2025-07-02 06:41:17.799     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.799         g = []
2025-07-02 06:41:17.799         if alo < ahi:
2025-07-02 06:41:17.799             if blo < bhi:
2025-07-02 06:41:17.799                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.799             else:
2025-07-02 06:41:17.799                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.799         elif blo < bhi:
2025-07-02 06:41:17.799             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.799
2025-07-02 06:41:17.799 >       yield from g
2025-07-02 06:41:17.799
2025-07-02 06:41:17.799 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.800 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.800
2025-07-02 06:41:17.800 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.800 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.800 alo = 292, ahi = 1101
2025-07-02 06:41:17.800 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.800 blo = 292, bhi = 1101
2025-07-02 06:41:17.800
2025-07-02 06:41:17.800     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.800         r"""
2025-07-02 06:41:17.800         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.800         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.800         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.800         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.800
2025-07-02 06:41:17.800         Example:
2025-07-02 06:41:17.800
2025-07-02 06:41:17.800         >>> d = Differ()
2025-07-02 06:41:17.800         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.801         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.801         >>> print(''.join(results), end="")
2025-07-02 06:41:17.801         - abcDefghiJkl
2025-07-02 06:41:17.801         + abcdefGhijkl
2025-07-02 06:41:17.801         """
2025-07-02 06:41:17.801
2025-07-02 06:41:17.801         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.801         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.801         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.801         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.801         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.801
2025-07-02 06:41:17.801         # search for the pair that matches best without being identical
2025-07-02 06:41:17.801         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.801         # on junk -- unless we have to)
2025-07-02 06:41:17.801         for j in range(blo, bhi):
2025-07-02 06:41:17.802             bj = b[j]
2025-07-02 06:41:17.802             cruncher.set_seq2(bj)
2025-07-02 06:41:17.802             for i in range(alo, ahi):
2025-07-02 06:41:17.802                 ai = a[i]
2025-07-02 06:41:17.802                 if ai == bj:
2025-07-02 06:41:17.802                     if eqi is None:
2025-07-02 06:41:17.802                         eqi, eqj = i, j
2025-07-02 06:41:17.802                     continue
2025-07-02 06:41:17.802                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.802                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.802                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.802                 # compares by a factor of 3.
2025-07-02 06:41:17.802                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.802                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.802                 # of the computation is cached by cruncher
2025-07-02 06:41:17.802                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.802                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.802                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.803                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.803         if best_ratio < cutoff:
2025-07-02 06:41:17.803             # no non-identical "pretty close" pair
2025-07-02 06:41:17.803             if eqi is None:
2025-07-02 06:41:17.803                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.803                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.803                 return
2025-07-02 06:41:17.803             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.803             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.803         else:
2025-07-02 06:41:17.803             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.803             eqi = None
2025-07-02 06:41:17.803
2025-07-02 06:41:17.803         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.803         # identical
2025-07-02 06:41:17.803
2025-07-02 06:41:17.803         # pump out diffs from before the synch point
2025-07-02 06:41:17.803         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.804
2025-07-02 06:41:17.804         # do intraline marking on the synch pair
2025-07-02 06:41:17.804         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.804         if eqi is None:
2025-07-02 06:41:17.804             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.804             atags = btags = ""
2025-07-02 06:41:17.804             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.804             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.804                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.804                 if tag == 'replace':
2025-07-02 06:41:17.804                     atags += '^' * la
2025-07-02 06:41:17.804                     btags += '^' * lb
2025-07-02 06:41:17.804                 elif tag == 'delete':
2025-07-02 06:41:17.804                     atags += '-' * la
2025-07-02 06:41:17.804                 elif tag == 'insert':
2025-07-02 06:41:17.804                     btags += '+' * lb
2025-07-02 06:41:17.804                 elif tag == 'equal':
2025-07-02 06:41:17.804                     atags += ' ' * la
2025-07-02 06:41:17.804                     btags += ' ' * lb
2025-07-02 06:41:17.805                 else:
2025-07-02 06:41:17.805                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.805             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.805         else:
2025-07-02 06:41:17.805             # the synch pair is identical
2025-07-02 06:41:17.805             yield '  ' + aelt
2025-07-02 06:41:17.805
2025-07-02 06:41:17.805         # pump out diffs from after the synch point
2025-07-02 06:41:17.805 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.805
2025-07-02 06:41:17.805 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.805 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.805
2025-07-02 06:41:17.805 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.805 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.805 alo = 293, ahi = 1101
2025-07-02 06:41:17.805 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.805 blo = 293, bhi = 1101
2025-07-02 06:41:17.806
2025-07-02 06:41:17.806     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.806         g = []
2025-07-02 06:41:17.806         if alo < ahi:
2025-07-02 06:41:17.806             if blo < bhi:
2025-07-02 06:41:17.806                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.806             else:
2025-07-02 06:41:17.806                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.806         elif blo < bhi:
2025-07-02 06:41:17.806             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.806
2025-07-02 06:41:17.806 >       yield from g
2025-07-02 06:41:17.806
2025-07-02 06:41:17.806 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.806 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.806
2025-07-02 06:41:17.806 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.806 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.806 alo = 293, ahi = 1101
2025-07-02 06:41:17.807 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.807 blo = 293, bhi = 1101
2025-07-02 06:41:17.807
2025-07-02 06:41:17.807     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.807         r"""
2025-07-02 06:41:17.807         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.807         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.807         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.807         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.807
2025-07-02 06:41:17.807         Example:
2025-07-02 06:41:17.807
2025-07-02 06:41:17.807         >>> d = Differ()
2025-07-02 06:41:17.807         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.807         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.807         >>> print(''.join(results), end="")
2025-07-02 06:41:17.807         - abcDefghiJkl
2025-07-02 06:41:17.807         + abcdefGhijkl
2025-07-02 06:41:17.808         """
2025-07-02 06:41:17.808
2025-07-02 06:41:17.808         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.808         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.808         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.808         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.808         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.808
2025-07-02 06:41:17.808         # search for the pair that matches best without being identical
2025-07-02 06:41:17.808         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.808         # on junk -- unless we have to)
2025-07-02 06:41:17.808         for j in range(blo, bhi):
2025-07-02 06:41:17.808             bj = b[j]
2025-07-02 06:41:17.808             cruncher.set_seq2(bj)
2025-07-02 06:41:17.808             for i in range(alo, ahi):
2025-07-02 06:41:17.808                 ai = a[i]
2025-07-02 06:41:17.808                 if ai == bj:
2025-07-02 06:41:17.808                     if eqi is None:
2025-07-02 06:41:17.808                         eqi, eqj = i, j
2025-07-02 06:41:17.809                     continue
2025-07-02 06:41:17.809                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.809                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.809                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.809                 # compares by a factor of 3.
2025-07-02 06:41:17.809                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.809                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.809                 # of the computation is cached by cruncher
2025-07-02 06:41:17.809                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.809                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.809                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.809                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.809         if best_ratio < cutoff:
2025-07-02 06:41:17.809             # no non-identical "pretty close" pair
2025-07-02 06:41:17.809             if eqi is None:
2025-07-02 06:41:17.809                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.809                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.809                 return
2025-07-02 06:41:17.809             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.810             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.810         else:
2025-07-02 06:41:17.810             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.810             eqi = None
2025-07-02 06:41:17.810
2025-07-02 06:41:17.810         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.810         # identical
2025-07-02 06:41:17.810
2025-07-02 06:41:17.810         # pump out diffs from before the synch point
2025-07-02 06:41:17.810         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.810
2025-07-02 06:41:17.810         # do intraline marking on the synch pair
2025-07-02 06:41:17.810         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.810         if eqi is None:
2025-07-02 06:41:17.810             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.810             atags = btags = ""
2025-07-02 06:41:17.810             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.810             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.810                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.810                 if tag == 'replace':
2025-07-02 06:41:17.811                     atags += '^' * la
2025-07-02 06:41:17.811                     btags += '^' * lb
2025-07-02 06:41:17.811                 elif tag == 'delete':
2025-07-02 06:41:17.811                     atags += '-' * la
2025-07-02 06:41:17.811                 elif tag == 'insert':
2025-07-02 06:41:17.811                     btags += '+' * lb
2025-07-02 06:41:17.811                 elif tag == 'equal':
2025-07-02 06:41:17.811                     atags += ' ' * la
2025-07-02 06:41:17.811                     btags += ' ' * lb
2025-07-02 06:41:17.811                 else:
2025-07-02 06:41:17.811                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.811             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.811         else:
2025-07-02 06:41:17.811             # the synch pair is identical
2025-07-02 06:41:17.811             yield '  ' + aelt
2025-07-02 06:41:17.811
2025-07-02 06:41:17.811         # pump out diffs from after the synch point
2025-07-02 06:41:17.811 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.811
2025-07-02 06:41:17.811 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.812 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.812
2025-07-02 06:41:17.812 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.812 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.812 alo = 294, ahi = 1101
2025-07-02 06:41:17.812 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.812 blo = 294, bhi = 1101
2025-07-02 06:41:17.812
2025-07-02 06:41:17.812     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.812         g = []
2025-07-02 06:41:17.812         if alo < ahi:
2025-07-02 06:41:17.812             if blo < bhi:
2025-07-02 06:41:17.812                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.812             else:
2025-07-02 06:41:17.812                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.812         elif blo < bhi:
2025-07-02 06:41:17.812             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.812
2025-07-02 06:41:17.812 >       yield from g
2025-07-02 06:41:17.812
2025-07-02 06:41:17.813 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.813 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.813
2025-07-02 06:41:17.813 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.813 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.813 alo = 294, ahi = 1101
2025-07-02 06:41:17.813 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.813 blo = 294, bhi = 1101
2025-07-02 06:41:17.813
2025-07-02 06:41:17.813     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.813         r"""
2025-07-02 06:41:17.813         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.813         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.813         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.813         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.813
2025-07-02 06:41:17.813         Example:
2025-07-02 06:41:17.813
2025-07-02 06:41:17.813         >>> d = Differ()
2025-07-02 06:41:17.813         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.814         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.814         >>> print(''.join(results), end="")
2025-07-02 06:41:17.814         - abcDefghiJkl
2025-07-02 06:41:17.814         + abcdefGhijkl
2025-07-02 06:41:17.814         """
2025-07-02 06:41:17.814
2025-07-02 06:41:17.814         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.814         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.814         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.814         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.814         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.814
2025-07-02 06:41:17.814         # search for the pair that matches best without being identical
2025-07-02 06:41:17.814         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.814         # on junk -- unless we have to)
2025-07-02 06:41:17.814         for j in range(blo, bhi):
2025-07-02 06:41:17.814             bj = b[j]
2025-07-02 06:41:17.814             cruncher.set_seq2(bj)
2025-07-02 06:41:17.814             for i in range(alo, ahi):
2025-07-02 06:41:17.815                 ai = a[i]
2025-07-02 06:41:17.815                 if ai == bj:
2025-07-02 06:41:17.815                     if eqi is None:
2025-07-02 06:41:17.815                         eqi, eqj = i, j
2025-07-02 06:41:17.815                     continue
2025-07-02 06:41:17.815                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.815                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.815                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.815                 # compares by a factor of 3.
2025-07-02 06:41:17.815                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.815                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.815                 # of the computation is cached by cruncher
2025-07-02 06:41:17.815                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.815                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.815                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.815                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.815         if best_ratio < cutoff:
2025-07-02 06:41:17.815             # no non-identical "pretty close" pair
2025-07-02 06:41:17.816             if eqi is None:
2025-07-02 06:41:17.816                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.816                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.816                 return
2025-07-02 06:41:17.816             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.816             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.816         else:
2025-07-02 06:41:17.816             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.816             eqi = None
2025-07-02 06:41:17.816
2025-07-02 06:41:17.816         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.816         # identical
2025-07-02 06:41:17.816
2025-07-02 06:41:17.816         # pump out diffs from before the synch point
2025-07-02 06:41:17.816         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.816
2025-07-02 06:41:17.816         # do intraline marking on the synch pair
2025-07-02 06:41:17.816         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.816         if eqi is None:
2025-07-02 06:41:17.816             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.817             atags = btags = ""
2025-07-02 06:41:17.817             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.817             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.817                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.817                 if tag == 'replace':
2025-07-02 06:41:17.817                     atags += '^' * la
2025-07-02 06:41:17.817                     btags += '^' * lb
2025-07-02 06:41:17.817                 elif tag == 'delete':
2025-07-02 06:41:17.817                     atags += '-' * la
2025-07-02 06:41:17.817                 elif tag == 'insert':
2025-07-02 06:41:17.817                     btags += '+' * lb
2025-07-02 06:41:17.817                 elif tag == 'equal':
2025-07-02 06:41:17.817                     atags += ' ' * la
2025-07-02 06:41:17.817                     btags += ' ' * lb
2025-07-02 06:41:17.817                 else:
2025-07-02 06:41:17.817                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.817             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.817         else:
2025-07-02 06:41:17.817             # the synch pair is identical
2025-07-02 06:41:17.817             yield '  ' + aelt
2025-07-02 06:41:17.818
2025-07-02 06:41:17.818         # pump out diffs from after the synch point
2025-07-02 06:41:17.818 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.818
2025-07-02 06:41:17.818 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.818 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.818
2025-07-02 06:41:17.818 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.818 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.818 alo = 295, ahi = 1101
2025-07-02 06:41:17.818 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.818 blo = 295, bhi = 1101
2025-07-02 06:41:17.818
2025-07-02 06:41:17.818     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.818         g = []
2025-07-02 06:41:17.818         if alo < ahi:
2025-07-02 06:41:17.818             if blo < bhi:
2025-07-02 06:41:17.818                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.818             else:
2025-07-02 06:41:17.818                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.819         elif blo < bhi:
2025-07-02 06:41:17.819             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.819
2025-07-02 06:41:17.819 >       yield from g
2025-07-02 06:41:17.819
2025-07-02 06:41:17.819 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.819 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.819
2025-07-02 06:41:17.819 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.819 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.819 alo = 295, ahi = 1101
2025-07-02 06:41:17.819 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.819 blo = 295, bhi = 1101
2025-07-02 06:41:17.819
2025-07-02 06:41:17.819     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.819         r"""
2025-07-02 06:41:17.819         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.819         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.819         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.819         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.819
2025-07-02 06:41:17.820         Example:
2025-07-02 06:41:17.820
2025-07-02 06:41:17.820         >>> d = Differ()
2025-07-02 06:41:17.820         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.820         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.820         >>> print(''.join(results), end="")
2025-07-02 06:41:17.820         - abcDefghiJkl
2025-07-02 06:41:17.820         + abcdefGhijkl
2025-07-02 06:41:17.820         """
2025-07-02 06:41:17.820
2025-07-02 06:41:17.820         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.820         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.820         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.820         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.820         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.820
2025-07-02 06:41:17.820         # search for the pair that matches best without being identical
2025-07-02 06:41:17.820         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.821         # on junk -- unless we have to)
2025-07-02 06:41:17.821         for j in range(blo, bhi):
2025-07-02 06:41:17.821             bj = b[j]
2025-07-02 06:41:17.821             cruncher.set_seq2(bj)
2025-07-02 06:41:17.821             for i in range(alo, ahi):
2025-07-02 06:41:17.821                 ai = a[i]
2025-07-02 06:41:17.821                 if ai == bj:
2025-07-02 06:41:17.821                     if eqi is None:
2025-07-02 06:41:17.821                         eqi, eqj = i, j
2025-07-02 06:41:17.821                     continue
2025-07-02 06:41:17.821                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.821                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.821                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.821                 # compares by a factor of 3.
2025-07-02 06:41:17.821                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.821                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.821                 # of the computation is cached by cruncher
2025-07-02 06:41:17.821                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.822                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.822                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.822                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.822         if best_ratio < cutoff:
2025-07-02 06:41:17.822             # no non-identical "pretty close" pair
2025-07-02 06:41:17.822             if eqi is None:
2025-07-02 06:41:17.822                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.822                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.822                 return
2025-07-02 06:41:17.822             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.822             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.822         else:
2025-07-02 06:41:17.822             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.822             eqi = None
2025-07-02 06:41:17.822
2025-07-02 06:41:17.822         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.822         # identical
2025-07-02 06:41:17.822
2025-07-02 06:41:17.822         # pump out diffs from before the synch point
2025-07-02 06:41:17.822         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.823
2025-07-02 06:41:17.823         # do intraline marking on the synch pair
2025-07-02 06:41:17.823         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.823         if eqi is None:
2025-07-02 06:41:17.823             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.823             atags = btags = ""
2025-07-02 06:41:17.823             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.823             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.823                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.823                 if tag == 'replace':
2025-07-02 06:41:17.823                     atags += '^' * la
2025-07-02 06:41:17.823                     btags += '^' * lb
2025-07-02 06:41:17.823                 elif tag == 'delete':
2025-07-02 06:41:17.823                     atags += '-' * la
2025-07-02 06:41:17.823                 elif tag == 'insert':
2025-07-02 06:41:17.823                     btags += '+' * lb
2025-07-02 06:41:17.823                 elif tag == 'equal':
2025-07-02 06:41:17.823                     atags += ' ' * la
2025-07-02 06:41:17.823                     btags += ' ' * lb
2025-07-02 06:41:17.824                 else:
2025-07-02 06:41:17.824                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.824             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.824         else:
2025-07-02 06:41:17.824             # the synch pair is identical
2025-07-02 06:41:17.824             yield '  ' + aelt
2025-07-02 06:41:17.824
2025-07-02 06:41:17.824         # pump out diffs from after the synch point
2025-07-02 06:41:17.824 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.824
2025-07-02 06:41:17.824 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.824 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.824
2025-07-02 06:41:17.824 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.824 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.824 alo = 296, ahi = 1101
2025-07-02 06:41:17.824 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.824 blo = 296, bhi = 1101
2025-07-02 06:41:17.824
2025-07-02 06:41:17.825     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.825         g = []
2025-07-02 06:41:17.825         if alo < ahi:
2025-07-02 06:41:17.825             if blo < bhi:
2025-07-02 06:41:17.825                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.825             else:
2025-07-02 06:41:17.825                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.825         elif blo < bhi:
2025-07-02 06:41:17.825             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.825
2025-07-02 06:41:17.825 >       yield from g
2025-07-02 06:41:17.825
2025-07-02 06:41:17.825 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.825 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.825
2025-07-02 06:41:17.825 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.825 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.825 alo = 296, ahi = 1101
2025-07-02 06:41:17.825 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.825 blo = 296, bhi = 1101
2025-07-02 06:41:17.826
2025-07-02 06:41:17.826     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.826         r"""
2025-07-02 06:41:17.826         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.826         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.826         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.826         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.826
2025-07-02 06:41:17.826         Example:
2025-07-02 06:41:17.826
2025-07-02 06:41:17.826         >>> d = Differ()
2025-07-02 06:41:17.826         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.826         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.826         >>> print(''.join(results), end="")
2025-07-02 06:41:17.826         - abcDefghiJkl
2025-07-02 06:41:17.826         + abcdefGhijkl
2025-07-02 06:41:17.826         """
2025-07-02 06:41:17.826
2025-07-02 06:41:17.827         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.827         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.827         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.827         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.827         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.827
2025-07-02 06:41:17.827         # search for the pair that matches best without being identical
2025-07-02 06:41:17.827         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.827         # on junk -- unless we have to)
2025-07-02 06:41:17.827         for j in range(blo, bhi):
2025-07-02 06:41:17.827             bj = b[j]
2025-07-02 06:41:17.827             cruncher.set_seq2(bj)
2025-07-02 06:41:17.827             for i in range(alo, ahi):
2025-07-02 06:41:17.827                 ai = a[i]
2025-07-02 06:41:17.827                 if ai == bj:
2025-07-02 06:41:17.827                     if eqi is None:
2025-07-02 06:41:17.827                         eqi, eqj = i, j
2025-07-02 06:41:17.827                     continue
2025-07-02 06:41:17.827                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.827                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.827                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.828                 # compares by a factor of 3.
2025-07-02 06:41:17.828                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.828                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.828                 # of the computation is cached by cruncher
2025-07-02 06:41:17.828                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.828                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.828                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.828                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.828         if best_ratio < cutoff:
2025-07-02 06:41:17.828             # no non-identical "pretty close" pair
2025-07-02 06:41:17.828             if eqi is None:
2025-07-02 06:41:17.828                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.828                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.828                 return
2025-07-02 06:41:17.828             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.828             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.828         else:
2025-07-02 06:41:17.828             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.828             eqi = None
2025-07-02 06:41:17.829
2025-07-02 06:41:17.829         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.829         # identical
2025-07-02 06:41:17.829
2025-07-02 06:41:17.829         # pump out diffs from before the synch point
2025-07-02 06:41:17.829         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.829
2025-07-02 06:41:17.829         # do intraline marking on the synch pair
2025-07-02 06:41:17.829         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.829         if eqi is None:
2025-07-02 06:41:17.829             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.829             atags = btags = ""
2025-07-02 06:41:17.829             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.829             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.829                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.829                 if tag == 'replace':
2025-07-02 06:41:17.829                     atags += '^' * la
2025-07-02 06:41:17.829                     btags += '^' * lb
2025-07-02 06:41:17.829                 elif tag == 'delete':
2025-07-02 06:41:17.829                     atags += '-' * la
2025-07-02 06:41:17.829                 elif tag == 'insert':
2025-07-02 06:41:17.830                     btags += '+' * lb
2025-07-02 06:41:17.830                 elif tag == 'equal':
2025-07-02 06:41:17.830                     atags += ' ' * la
2025-07-02 06:41:17.830                     btags += ' ' * lb
2025-07-02 06:41:17.830                 else:
2025-07-02 06:41:17.830                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.830             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.830         else:
2025-07-02 06:41:17.830             # the synch pair is identical
2025-07-02 06:41:17.830             yield '  ' + aelt
2025-07-02 06:41:17.830
2025-07-02 06:41:17.830         # pump out diffs from after the synch point
2025-07-02 06:41:17.830 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.830
2025-07-02 06:41:17.830 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.830 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.830
2025-07-02 06:41:17.830 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.830 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.830 alo = 297, ahi = 1101
2025-07-02 06:41:17.831 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.831 blo = 297, bhi = 1101
2025-07-02 06:41:17.831
2025-07-02 06:41:17.831     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.831         g = []
2025-07-02 06:41:17.831         if alo < ahi:
2025-07-02 06:41:17.831             if blo < bhi:
2025-07-02 06:41:17.831                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.831             else:
2025-07-02 06:41:17.831                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.831         elif blo < bhi:
2025-07-02 06:41:17.831             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.831
2025-07-02 06:41:17.831 >       yield from g
2025-07-02 06:41:17.831
2025-07-02 06:41:17.831 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.831 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.831
2025-07-02 06:41:17.831 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.831 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.832 alo = 297, ahi = 1101
2025-07-02 06:41:17.832 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.832 blo = 297, bhi = 1101
2025-07-02 06:41:17.832
2025-07-02 06:41:17.832     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.832         r"""
2025-07-02 06:41:17.832         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.832         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.832         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.832         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.832
2025-07-02 06:41:17.832         Example:
2025-07-02 06:41:17.832
2025-07-02 06:41:17.832         >>> d = Differ()
2025-07-02 06:41:17.832         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.832         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.832         >>> print(''.join(results), end="")
2025-07-02 06:41:17.832         - abcDefghiJkl
2025-07-02 06:41:17.833         + abcdefGhijkl
2025-07-02 06:41:17.833         """
2025-07-02 06:41:17.833
2025-07-02 06:41:17.833         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.833         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.833         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.833         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.833         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.833
2025-07-02 06:41:17.833         # search for the pair that matches best without being identical
2025-07-02 06:41:17.833         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.833         # on junk -- unless we have to)
2025-07-02 06:41:17.833         for j in range(blo, bhi):
2025-07-02 06:41:17.833             bj = b[j]
2025-07-02 06:41:17.833             cruncher.set_seq2(bj)
2025-07-02 06:41:17.833             for i in range(alo, ahi):
2025-07-02 06:41:17.833                 ai = a[i]
2025-07-02 06:41:17.833                 if ai == bj:
2025-07-02 06:41:17.833                     if eqi is None:
2025-07-02 06:41:17.834                         eqi, eqj = i, j
2025-07-02 06:41:17.834                     continue
2025-07-02 06:41:17.834                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.834                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.834                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.834                 # compares by a factor of 3.
2025-07-02 06:41:17.834                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.834                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.834                 # of the computation is cached by cruncher
2025-07-02 06:41:17.834                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.834                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.834                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.834                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.834         if best_ratio < cutoff:
2025-07-02 06:41:17.834             # no non-identical "pretty close" pair
2025-07-02 06:41:17.834             if eqi is None:
2025-07-02 06:41:17.834                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.834                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.834                 return
2025-07-02 06:41:17.834             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.835             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.835         else:
2025-07-02 06:41:17.835             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.835             eqi = None
2025-07-02 06:41:17.835
2025-07-02 06:41:17.835         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.835         # identical
2025-07-02 06:41:17.835
2025-07-02 06:41:17.835         # pump out diffs from before the synch point
2025-07-02 06:41:17.835         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.835
2025-07-02 06:41:17.835         # do intraline marking on the synch pair
2025-07-02 06:41:17.835         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.835         if eqi is None:
2025-07-02 06:41:17.835             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.835             atags = btags = ""
2025-07-02 06:41:17.835             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.835             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.836                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.836                 if tag == 'replace':
2025-07-02 06:41:17.836                     atags += '^' * la
2025-07-02 06:41:17.836                     btags += '^' * lb
2025-07-02 06:41:17.836                 elif tag == 'delete':
2025-07-02 06:41:17.836                     atags += '-' * la
2025-07-02 06:41:17.836                 elif tag == 'insert':
2025-07-02 06:41:17.836                     btags += '+' * lb
2025-07-02 06:41:17.836                 elif tag == 'equal':
2025-07-02 06:41:17.836                     atags += ' ' * la
2025-07-02 06:41:17.836                     btags += ' ' * lb
2025-07-02 06:41:17.836                 else:
2025-07-02 06:41:17.836                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.836             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.836         else:
2025-07-02 06:41:17.836             # the synch pair is identical
2025-07-02 06:41:17.836             yield '  ' + aelt
2025-07-02 06:41:17.836
2025-07-02 06:41:17.836         # pump out diffs from after the synch point
2025-07-02 06:41:17.836 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.837
2025-07-02 06:41:17.837 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.837 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.837
2025-07-02 06:41:17.837 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.837 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.837 alo = 298, ahi = 1101
2025-07-02 06:41:17.837 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.837 blo = 298, bhi = 1101
2025-07-02 06:41:17.837
2025-07-02 06:41:17.837     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.837         g = []
2025-07-02 06:41:17.837         if alo < ahi:
2025-07-02 06:41:17.837             if blo < bhi:
2025-07-02 06:41:17.837                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.837             else:
2025-07-02 06:41:17.837                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.838         elif blo < bhi:
2025-07-02 06:41:17.838             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.838
2025-07-02 06:41:17.838 >       yield from g
2025-07-02 06:41:17.838
2025-07-02 06:41:17.838 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.838 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.838
2025-07-02 06:41:17.838 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.838 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.838 alo = 298, ahi = 1101
2025-07-02 06:41:17.838 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.838 blo = 298, bhi = 1101
2025-07-02 06:41:17.838
2025-07-02 06:41:17.838     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.838         r"""
2025-07-02 06:41:17.838         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.838         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.838         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.838         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.839
2025-07-02 06:41:17.839         Example:
2025-07-02 06:41:17.839
2025-07-02 06:41:17.839         >>> d = Differ()
2025-07-02 06:41:17.839         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.839         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.839         >>> print(''.join(results), end="")
2025-07-02 06:41:17.839         - abcDefghiJkl
2025-07-02 06:41:17.839         + abcdefGhijkl
2025-07-02 06:41:17.839         """
2025-07-02 06:41:17.839
2025-07-02 06:41:17.839         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.839         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.839         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.839         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.839         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.839
2025-07-02 06:41:17.839         # search for the pair that matches best without being identical
2025-07-02 06:41:17.839         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.840         # on junk -- unless we have to)
2025-07-02 06:41:17.840         for j in range(blo, bhi):
2025-07-02 06:41:17.840             bj = b[j]
2025-07-02 06:41:17.840             cruncher.set_seq2(bj)
2025-07-02 06:41:17.840             for i in range(alo, ahi):
2025-07-02 06:41:17.840                 ai = a[i]
2025-07-02 06:41:17.840                 if ai == bj:
2025-07-02 06:41:17.840                     if eqi is None:
2025-07-02 06:41:17.840                         eqi, eqj = i, j
2025-07-02 06:41:17.840                     continue
2025-07-02 06:41:17.840                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.840                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.840                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.840                 # compares by a factor of 3.
2025-07-02 06:41:17.840                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.840                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.840                 # of the computation is cached by cruncher
2025-07-02 06:41:17.840                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.840                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.840                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.841                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.841         if best_ratio < cutoff:
2025-07-02 06:41:17.841             # no non-identical "pretty close" pair
2025-07-02 06:41:17.841             if eqi is None:
2025-07-02 06:41:17.841                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.841                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.841                 return
2025-07-02 06:41:17.841             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.841             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.841         else:
2025-07-02 06:41:17.841             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.841             eqi = None
2025-07-02 06:41:17.841
2025-07-02 06:41:17.841         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.841         # identical
2025-07-02 06:41:17.841
2025-07-02 06:41:17.841         # pump out diffs from before the synch point
2025-07-02 06:41:17.841         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.841
2025-07-02 06:41:17.842         # do intraline marking on the synch pair
2025-07-02 06:41:17.842         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.842         if eqi is None:
2025-07-02 06:41:17.842             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.842             atags = btags = ""
2025-07-02 06:41:17.842             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.842             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.842                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.842                 if tag == 'replace':
2025-07-02 06:41:17.842                     atags += '^' * la
2025-07-02 06:41:17.842                     btags += '^' * lb
2025-07-02 06:41:17.842                 elif tag == 'delete':
2025-07-02 06:41:17.842                     atags += '-' * la
2025-07-02 06:41:17.842                 elif tag == 'insert':
2025-07-02 06:41:17.842                     btags += '+' * lb
2025-07-02 06:41:17.842                 elif tag == 'equal':
2025-07-02 06:41:17.842                     atags += ' ' * la
2025-07-02 06:41:17.842                     btags += ' ' * lb
2025-07-02 06:41:17.842                 else:
2025-07-02 06:41:17.842                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.843             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.843         else:
2025-07-02 06:41:17.843             # the synch pair is identical
2025-07-02 06:41:17.843             yield '  ' + aelt
2025-07-02 06:41:17.843
2025-07-02 06:41:17.843         # pump out diffs from after the synch point
2025-07-02 06:41:17.843 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.843
2025-07-02 06:41:17.843 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.843 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.843
2025-07-02 06:41:17.843 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.843 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.843 alo = 299, ahi = 1101
2025-07-02 06:41:17.843 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.843 blo = 299, bhi = 1101
2025-07-02 06:41:17.844
2025-07-02 06:41:17.844     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.844         g = []
2025-07-02 06:41:17.844         if alo < ahi:
2025-07-02 06:41:17.844             if blo < bhi:
2025-07-02 06:41:17.844                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.844             else:
2025-07-02 06:41:17.844                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.844         elif blo < bhi:
2025-07-02 06:41:17.844             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.844
2025-07-02 06:41:17.844 >       yield from g
2025-07-02 06:41:17.844
2025-07-02 06:41:17.844 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.844 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.844
2025-07-02 06:41:17.844 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.844 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.844 alo = 299, ahi = 1101
2025-07-02 06:41:17.844 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.845 blo = 299, bhi = 1101
2025-07-02 06:41:17.845
2025-07-02 06:41:17.845     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.845         r"""
2025-07-02 06:41:17.845         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.845         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.845         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.845         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.845
2025-07-02 06:41:17.845         Example:
2025-07-02 06:41:17.845
2025-07-02 06:41:17.845         >>> d = Differ()
2025-07-02 06:41:17.845         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.845         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.845         >>> print(''.join(results), end="")
2025-07-02 06:41:17.845         - abcDefghiJkl
2025-07-02 06:41:17.845         + abcdefGhijkl
2025-07-02 06:41:17.845         """
2025-07-02 06:41:17.845
2025-07-02 06:41:17.846         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.846         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.846         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.846         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.846         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.846
2025-07-02 06:41:17.846         # search for the pair that matches best without being identical
2025-07-02 06:41:17.846         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.846         # on junk -- unless we have to)
2025-07-02 06:41:17.846         for j in range(blo, bhi):
2025-07-02 06:41:17.846             bj = b[j]
2025-07-02 06:41:17.846             cruncher.set_seq2(bj)
2025-07-02 06:41:17.846             for i in range(alo, ahi):
2025-07-02 06:41:17.846                 ai = a[i]
2025-07-02 06:41:17.846                 if ai == bj:
2025-07-02 06:41:17.846                     if eqi is None:
2025-07-02 06:41:17.846                         eqi, eqj = i, j
2025-07-02 06:41:17.846                     continue
2025-07-02 06:41:17.846                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.846                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.847                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.847                 # compares by a factor of 3.
2025-07-02 06:41:17.847                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.847                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.847                 # of the computation is cached by cruncher
2025-07-02 06:41:17.847                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.847                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.847                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.847                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.847         if best_ratio < cutoff:
2025-07-02 06:41:17.847             # no non-identical "pretty close" pair
2025-07-02 06:41:17.847             if eqi is None:
2025-07-02 06:41:17.847                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.847                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.847                 return
2025-07-02 06:41:17.847             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.847             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.847         else:
2025-07-02 06:41:17.847             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.847             eqi = None
2025-07-02 06:41:17.848
2025-07-02 06:41:17.848         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.848         # identical
2025-07-02 06:41:17.848
2025-07-02 06:41:17.848         # pump out diffs from before the synch point
2025-07-02 06:41:17.848         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.848
2025-07-02 06:41:17.848         # do intraline marking on the synch pair
2025-07-02 06:41:17.848         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.848         if eqi is None:
2025-07-02 06:41:17.848             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.848             atags = btags = ""
2025-07-02 06:41:17.848             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.848             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.848                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.848                 if tag == 'replace':
2025-07-02 06:41:17.848                     atags += '^' * la
2025-07-02 06:41:17.848                     btags += '^' * lb
2025-07-02 06:41:17.848                 elif tag == 'delete':
2025-07-02 06:41:17.848                     atags += '-' * la
2025-07-02 06:41:17.848                 elif tag == 'insert':
2025-07-02 06:41:17.849                     btags += '+' * lb
2025-07-02 06:41:17.849                 elif tag == 'equal':
2025-07-02 06:41:17.849                     atags += ' ' * la
2025-07-02 06:41:17.849                     btags += ' ' * lb
2025-07-02 06:41:17.849                 else:
2025-07-02 06:41:17.849                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.849             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.849         else:
2025-07-02 06:41:17.849             # the synch pair is identical
2025-07-02 06:41:17.849             yield '  ' + aelt
2025-07-02 06:41:17.849
2025-07-02 06:41:17.849         # pump out diffs from after the synch point
2025-07-02 06:41:17.849 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.849
2025-07-02 06:41:17.849 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.849 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.849
2025-07-02 06:41:17.849 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.849 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.849 alo = 300, ahi = 1101
2025-07-02 06:41:17.850 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.850 blo = 300, bhi = 1101
2025-07-02 06:41:17.850
2025-07-02 06:41:17.850     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.850         g = []
2025-07-02 06:41:17.850         if alo < ahi:
2025-07-02 06:41:17.850             if blo < bhi:
2025-07-02 06:41:17.850                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.850             else:
2025-07-02 06:41:17.850                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.850         elif blo < bhi:
2025-07-02 06:41:17.850             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.850
2025-07-02 06:41:17.850 >       yield from g
2025-07-02 06:41:17.850
2025-07-02 06:41:17.850 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.850 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.850
2025-07-02 06:41:17.850 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.851 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.851 alo = 300, ahi = 1101
2025-07-02 06:41:17.851 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.851 blo = 300, bhi = 1101
2025-07-02 06:41:17.851
2025-07-02 06:41:17.851     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.851         r"""
2025-07-02 06:41:17.851         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.851         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.851         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.851         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.851
2025-07-02 06:41:17.851         Example:
2025-07-02 06:41:17.851
2025-07-02 06:41:17.851         >>> d = Differ()
2025-07-02 06:41:17.851         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.851         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.851         >>> print(''.join(results), end="")
2025-07-02 06:41:17.851         - abcDefghiJkl
2025-07-02 06:41:17.852         + abcdefGhijkl
2025-07-02 06:41:17.852         """
2025-07-02 06:41:17.852
2025-07-02 06:41:17.852         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.852         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.852         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.852         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.852         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.852
2025-07-02 06:41:17.852         # search for the pair that matches best without being identical
2025-07-02 06:41:17.852         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.852         # on junk -- unless we have to)
2025-07-02 06:41:17.852         for j in range(blo, bhi):
2025-07-02 06:41:17.852             bj = b[j]
2025-07-02 06:41:17.852             cruncher.set_seq2(bj)
2025-07-02 06:41:17.852             for i in range(alo, ahi):
2025-07-02 06:41:17.852                 ai = a[i]
2025-07-02 06:41:17.852                 if ai == bj:
2025-07-02 06:41:17.852                     if eqi is None:
2025-07-02 06:41:17.853                         eqi, eqj = i, j
2025-07-02 06:41:17.853                     continue
2025-07-02 06:41:17.853                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.853                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.853                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.853                 # compares by a factor of 3.
2025-07-02 06:41:17.853                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.853                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.853                 # of the computation is cached by cruncher
2025-07-02 06:41:17.853                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.853                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.853                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.853                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.853         if best_ratio < cutoff:
2025-07-02 06:41:17.853             # no non-identical "pretty close" pair
2025-07-02 06:41:17.853             if eqi is None:
2025-07-02 06:41:17.853                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.854                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.854                 return
2025-07-02 06:41:17.854             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.854             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.854         else:
2025-07-02 06:41:17.854             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.854             eqi = None
2025-07-02 06:41:17.854
2025-07-02 06:41:17.854         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.854         # identical
2025-07-02 06:41:17.854
2025-07-02 06:41:17.854         # pump out diffs from before the synch point
2025-07-02 06:41:17.854         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.854
2025-07-02 06:41:17.854         # do intraline marking on the synch pair
2025-07-02 06:41:17.854         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.854         if eqi is None:
2025-07-02 06:41:17.854             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.854             atags = btags = ""
2025-07-02 06:41:17.855             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.855             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.855                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.855                 if tag == 'replace':
2025-07-02 06:41:17.855                     atags += '^' * la
2025-07-02 06:41:17.855                     btags += '^' * lb
2025-07-02 06:41:17.855                 elif tag == 'delete':
2025-07-02 06:41:17.855                     atags += '-' * la
2025-07-02 06:41:17.855                 elif tag == 'insert':
2025-07-02 06:41:17.855                     btags += '+' * lb
2025-07-02 06:41:17.855                 elif tag == 'equal':
2025-07-02 06:41:17.855                     atags += ' ' * la
2025-07-02 06:41:17.855                     btags += ' ' * lb
2025-07-02 06:41:17.855                 else:
2025-07-02 06:41:17.855                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.855             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.855         else:
2025-07-02 06:41:17.855             # the synch pair is identical
2025-07-02 06:41:17.855             yield '  ' + aelt
2025-07-02 06:41:17.855
2025-07-02 06:41:17.856         # pump out diffs from after the synch point
2025-07-02 06:41:17.856 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.856
2025-07-02 06:41:17.856 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.856 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.856
2025-07-02 06:41:17.856 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.856 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.856 alo = 301, ahi = 1101
2025-07-02 06:41:17.856 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.856 blo = 301, bhi = 1101
2025-07-02 06:41:17.856
2025-07-02 06:41:17.856     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.856         g = []
2025-07-02 06:41:17.856         if alo < ahi:
2025-07-02 06:41:17.856             if blo < bhi:
2025-07-02 06:41:17.856                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.856             else:
2025-07-02 06:41:17.856                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.857         elif blo < bhi:
2025-07-02 06:41:17.857             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.857
2025-07-02 06:41:17.857 >       yield from g
2025-07-02 06:41:17.857
2025-07-02 06:41:17.857 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.857 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.857
2025-07-02 06:41:17.857 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.857 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.857 alo = 301, ahi = 1101
2025-07-02 06:41:17.857 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.857 blo = 301, bhi = 1101
2025-07-02 06:41:17.857
2025-07-02 06:41:17.857     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.857         r"""
2025-07-02 06:41:17.857         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.857         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.857         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.857         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.858
2025-07-02 06:41:17.858         Example:
2025-07-02 06:41:17.858
2025-07-02 06:41:17.858         >>> d = Differ()
2025-07-02 06:41:17.858         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.858         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.858         >>> print(''.join(results), end="")
2025-07-02 06:41:17.858         - abcDefghiJkl
2025-07-02 06:41:17.858         + abcdefGhijkl
2025-07-02 06:41:17.858         """
2025-07-02 06:41:17.858
2025-07-02 06:41:17.858         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.858         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.858         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.858         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.858         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.859
2025-07-02 06:41:17.859         # search for the pair that matches best without being identical
2025-07-02 06:41:17.859         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.859         # on junk -- unless we have to)
2025-07-02 06:41:17.859         for j in range(blo, bhi):
2025-07-02 06:41:17.859             bj = b[j]
2025-07-02 06:41:17.859             cruncher.set_seq2(bj)
2025-07-02 06:41:17.859             for i in range(alo, ahi):
2025-07-02 06:41:17.859                 ai = a[i]
2025-07-02 06:41:17.859                 if ai == bj:
2025-07-02 06:41:17.859                     if eqi is None:
2025-07-02 06:41:17.859                         eqi, eqj = i, j
2025-07-02 06:41:17.859                     continue
2025-07-02 06:41:17.859                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.859                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.859                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.859                 # compares by a factor of 3.
2025-07-02 06:41:17.859                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.859                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.860                 # of the computation is cached by cruncher
2025-07-02 06:41:17.860                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.860                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.860                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.860                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.860         if best_ratio < cutoff:
2025-07-02 06:41:17.860             # no non-identical "pretty close" pair
2025-07-02 06:41:17.860             if eqi is None:
2025-07-02 06:41:17.860                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.860                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.860                 return
2025-07-02 06:41:17.860             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.860             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.860         else:
2025-07-02 06:41:17.860             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.860             eqi = None
2025-07-02 06:41:17.860
2025-07-02 06:41:17.860         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.860         # identical
2025-07-02 06:41:17.861
2025-07-02 06:41:17.861         # pump out diffs from before the synch point
2025-07-02 06:41:17.861         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.861
2025-07-02 06:41:17.861         # do intraline marking on the synch pair
2025-07-02 06:41:17.861         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.861         if eqi is None:
2025-07-02 06:41:17.861             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.861             atags = btags = ""
2025-07-02 06:41:17.861             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.861             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.861                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.861                 if tag == 'replace':
2025-07-02 06:41:17.861                     atags += '^' * la
2025-07-02 06:41:17.861                     btags += '^' * lb
2025-07-02 06:41:17.861                 elif tag == 'delete':
2025-07-02 06:41:17.861                     atags += '-' * la
2025-07-02 06:41:17.861                 elif tag == 'insert':
2025-07-02 06:41:17.861                     btags += '+' * lb
2025-07-02 06:41:17.861                 elif tag == 'equal':
2025-07-02 06:41:17.861                     atags += ' ' * la
2025-07-02 06:41:17.862                     btags += ' ' * lb
2025-07-02 06:41:17.862                 else:
2025-07-02 06:41:17.862                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.862             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.862         else:
2025-07-02 06:41:17.862             # the synch pair is identical
2025-07-02 06:41:17.862             yield '  ' + aelt
2025-07-02 06:41:17.862
2025-07-02 06:41:17.862         # pump out diffs from after the synch point
2025-07-02 06:41:17.862 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.862
2025-07-02 06:41:17.862 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.862 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.862
2025-07-02 06:41:17.862 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.862 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.862 alo = 302, ahi = 1101
2025-07-02 06:41:17.862 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.862 blo = 302, bhi = 1101
2025-07-02 06:41:17.862
2025-07-02 06:41:17.863     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.863         g = []
2025-07-02 06:41:17.863         if alo < ahi:
2025-07-02 06:41:17.863             if blo < bhi:
2025-07-02 06:41:17.863                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.863             else:
2025-07-02 06:41:17.863                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.863         elif blo < bhi:
2025-07-02 06:41:17.863             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.863
2025-07-02 06:41:17.863 >       yield from g
2025-07-02 06:41:17.863
2025-07-02 06:41:17.863 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.863 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.863
2025-07-02 06:41:17.863 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.863 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.863 alo = 302, ahi = 1101
2025-07-02 06:41:17.863 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.863 blo = 302, bhi = 1101
2025-07-02 06:41:17.864
2025-07-02 06:41:17.864     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.864         r"""
2025-07-02 06:41:17.864         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.864         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.864         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.864         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.864
2025-07-02 06:41:17.864         Example:
2025-07-02 06:41:17.864
2025-07-02 06:41:17.864         >>> d = Differ()
2025-07-02 06:41:17.864         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.864         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.864         >>> print(''.join(results), end="")
2025-07-02 06:41:17.864         - abcDefghiJkl
2025-07-02 06:41:17.864         + abcdefGhijkl
2025-07-02 06:41:17.864         """
2025-07-02 06:41:17.864
2025-07-02 06:41:17.865         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.865         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.865         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.865         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.865         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.865
2025-07-02 06:41:17.865         # search for the pair that matches best without being identical
2025-07-02 06:41:17.865         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.865         # on junk -- unless we have to)
2025-07-02 06:41:17.865         for j in range(blo, bhi):
2025-07-02 06:41:17.865             bj = b[j]
2025-07-02 06:41:17.865             cruncher.set_seq2(bj)
2025-07-02 06:41:17.865             for i in range(alo, ahi):
2025-07-02 06:41:17.865                 ai = a[i]
2025-07-02 06:41:17.865                 if ai == bj:
2025-07-02 06:41:17.865                     if eqi is None:
2025-07-02 06:41:17.865                         eqi, eqj = i, j
2025-07-02 06:41:17.865                     continue
2025-07-02 06:41:17.865                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.865                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.865                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.866                 # compares by a factor of 3.
2025-07-02 06:41:17.866                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.866                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.866                 # of the computation is cached by cruncher
2025-07-02 06:41:17.866                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.866                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.866                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.866                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.866         if best_ratio < cutoff:
2025-07-02 06:41:17.866             # no non-identical "pretty close" pair
2025-07-02 06:41:17.866             if eqi is None:
2025-07-02 06:41:17.866                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.866                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.866                 return
2025-07-02 06:41:17.866             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.866             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.866         else:
2025-07-02 06:41:17.866             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.866             eqi = None
2025-07-02 06:41:17.866
2025-07-02 06:41:17.867         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.867         # identical
2025-07-02 06:41:17.867
2025-07-02 06:41:17.867         # pump out diffs from before the synch point
2025-07-02 06:41:17.867         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.867
2025-07-02 06:41:17.867         # do intraline marking on the synch pair
2025-07-02 06:41:17.867         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.867         if eqi is None:
2025-07-02 06:41:17.867             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.867             atags = btags = ""
2025-07-02 06:41:17.867             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.867             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.867                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.867                 if tag == 'replace':
2025-07-02 06:41:17.867                     atags += '^' * la
2025-07-02 06:41:17.867                     btags += '^' * lb
2025-07-02 06:41:17.867                 elif tag == 'delete':
2025-07-02 06:41:17.868                     atags += '-' * la
2025-07-02 06:41:17.868                 elif tag == 'insert':
2025-07-02 06:41:17.868                     btags += '+' * lb
2025-07-02 06:41:17.868                 elif tag == 'equal':
2025-07-02 06:41:17.868                     atags += ' ' * la
2025-07-02 06:41:17.868                     btags += ' ' * lb
2025-07-02 06:41:17.868                 else:
2025-07-02 06:41:17.868                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.868             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.868         else:
2025-07-02 06:41:17.868             # the synch pair is identical
2025-07-02 06:41:17.868             yield '  ' + aelt
2025-07-02 06:41:17.868
2025-07-02 06:41:17.868         # pump out diffs from after the synch point
2025-07-02 06:41:17.868 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.868
2025-07-02 06:41:17.868 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.868 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.869
2025-07-02 06:41:17.869 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.869 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.869 alo = 303, ahi = 1101
2025-07-02 06:41:17.869 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.869 blo = 303, bhi = 1101
2025-07-02 06:41:17.869
2025-07-02 06:41:17.869     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.869         g = []
2025-07-02 06:41:17.869         if alo < ahi:
2025-07-02 06:41:17.869             if blo < bhi:
2025-07-02 06:41:17.869                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.869             else:
2025-07-02 06:41:17.869                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.869         elif blo < bhi:
2025-07-02 06:41:17.869             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.869
2025-07-02 06:41:17.869 >       yield from g
2025-07-02 06:41:17.869
2025-07-02 06:41:17.870 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.870 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.870
2025-07-02 06:41:17.870 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.870 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.870 alo = 303, ahi = 1101
2025-07-02 06:41:17.870 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.870 blo = 303, bhi = 1101
2025-07-02 06:41:17.870
2025-07-02 06:41:17.870     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.870         r"""
2025-07-02 06:41:17.870         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.870         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.870         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.870         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.870
2025-07-02 06:41:17.870         Example:
2025-07-02 06:41:17.870
2025-07-02 06:41:17.870         >>> d = Differ()
2025-07-02 06:41:17.871         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.871         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.871         >>> print(''.join(results), end="")
2025-07-02 06:41:17.871         - abcDefghiJkl
2025-07-02 06:41:17.871         + abcdefGhijkl
2025-07-02 06:41:17.871         """
2025-07-02 06:41:17.871
2025-07-02 06:41:17.871         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.871         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.871         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.871         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.871         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.871
2025-07-02 06:41:17.871         # search for the pair that matches best without being identical
2025-07-02 06:41:17.871         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.871         # on junk -- unless we have to)
2025-07-02 06:41:17.871         for j in range(blo, bhi):
2025-07-02 06:41:17.871             bj = b[j]
2025-07-02 06:41:17.872             cruncher.set_seq2(bj)
2025-07-02 06:41:17.872             for i in range(alo, ahi):
2025-07-02 06:41:17.872                 ai = a[i]
2025-07-02 06:41:17.872                 if ai == bj:
2025-07-02 06:41:17.872                     if eqi is None:
2025-07-02 06:41:17.872                         eqi, eqj = i, j
2025-07-02 06:41:17.872                     continue
2025-07-02 06:41:17.872                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.872                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.872                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.872                 # compares by a factor of 3.
2025-07-02 06:41:17.872                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.872                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.872                 # of the computation is cached by cruncher
2025-07-02 06:41:17.872                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.872                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.872                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.872                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.872         if best_ratio < cutoff:
2025-07-02 06:41:17.873             # no non-identical "pretty close" pair
2025-07-02 06:41:17.873             if eqi is None:
2025-07-02 06:41:17.873                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.873                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.873                 return
2025-07-02 06:41:17.873             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.873             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.873         else:
2025-07-02 06:41:17.873             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.873             eqi = None
2025-07-02 06:41:17.873
2025-07-02 06:41:17.873         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.873         # identical
2025-07-02 06:41:17.873
2025-07-02 06:41:17.873         # pump out diffs from before the synch point
2025-07-02 06:41:17.873         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.873
2025-07-02 06:41:17.873         # do intraline marking on the synch pair
2025-07-02 06:41:17.873         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.874         if eqi is None:
2025-07-02 06:41:17.874             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.874             atags = btags = ""
2025-07-02 06:41:17.874             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.874             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.874                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.874                 if tag == 'replace':
2025-07-02 06:41:17.874                     atags += '^' * la
2025-07-02 06:41:17.874                     btags += '^' * lb
2025-07-02 06:41:17.874                 elif tag == 'delete':
2025-07-02 06:41:17.874                     atags += '-' * la
2025-07-02 06:41:17.874                 elif tag == 'insert':
2025-07-02 06:41:17.874                     btags += '+' * lb
2025-07-02 06:41:17.874                 elif tag == 'equal':
2025-07-02 06:41:17.874                     atags += ' ' * la
2025-07-02 06:41:17.874                     btags += ' ' * lb
2025-07-02 06:41:17.874                 else:
2025-07-02 06:41:17.874                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.874             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.874         else:
2025-07-02 06:41:17.875             # the synch pair is identical
2025-07-02 06:41:17.875             yield '  ' + aelt
2025-07-02 06:41:17.875
2025-07-02 06:41:17.875         # pump out diffs from after the synch point
2025-07-02 06:41:17.875 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.875
2025-07-02 06:41:17.875 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.875 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.875
2025-07-02 06:41:17.875 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.875 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.875 alo = 304, ahi = 1101
2025-07-02 06:41:17.875 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.875 blo = 304, bhi = 1101
2025-07-02 06:41:17.875
2025-07-02 06:41:17.875     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.875         g = []
2025-07-02 06:41:17.875         if alo < ahi:
2025-07-02 06:41:17.875             if blo < bhi:
2025-07-02 06:41:17.876                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.876             else:
2025-07-02 06:41:17.876                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.876         elif blo < bhi:
2025-07-02 06:41:17.876             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.876
2025-07-02 06:41:17.876 >       yield from g
2025-07-02 06:41:17.876
2025-07-02 06:41:17.876 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.876 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.876
2025-07-02 06:41:17.876 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.876 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.876 alo = 304, ahi = 1101
2025-07-02 06:41:17.876 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.876 blo = 304, bhi = 1101
2025-07-02 06:41:17.876
2025-07-02 06:41:17.876     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.876         r"""
2025-07-02 06:41:17.877         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.877         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.877         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.877         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.877
2025-07-02 06:41:17.877         Example:
2025-07-02 06:41:17.877
2025-07-02 06:41:17.877         >>> d = Differ()
2025-07-02 06:41:17.877         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.877         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.877         >>> print(''.join(results), end="")
2025-07-02 06:41:17.877         - abcDefghiJkl
2025-07-02 06:41:17.877         + abcdefGhijkl
2025-07-02 06:41:17.877         """
2025-07-02 06:41:17.877
2025-07-02 06:41:17.877         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.877         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.878         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.878         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.878         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.878
2025-07-02 06:41:17.878         # search for the pair that matches best without being identical
2025-07-02 06:41:17.878         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.878         # on junk -- unless we have to)
2025-07-02 06:41:17.878         for j in range(blo, bhi):
2025-07-02 06:41:17.878             bj = b[j]
2025-07-02 06:41:17.878             cruncher.set_seq2(bj)
2025-07-02 06:41:17.878             for i in range(alo, ahi):
2025-07-02 06:41:17.878                 ai = a[i]
2025-07-02 06:41:17.878                 if ai == bj:
2025-07-02 06:41:17.878                     if eqi is None:
2025-07-02 06:41:17.878                         eqi, eqj = i, j
2025-07-02 06:41:17.878                     continue
2025-07-02 06:41:17.878                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.878                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.878                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.879                 # compares by a factor of 3.
2025-07-02 06:41:17.879                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.879                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.879                 # of the computation is cached by cruncher
2025-07-02 06:41:17.879                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.879                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.879                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.879                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.879         if best_ratio < cutoff:
2025-07-02 06:41:17.879             # no non-identical "pretty close" pair
2025-07-02 06:41:17.879             if eqi is None:
2025-07-02 06:41:17.879                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.879                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.879                 return
2025-07-02 06:41:17.879             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.879             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.879         else:
2025-07-02 06:41:17.879             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.879             eqi = None
2025-07-02 06:41:17.880
2025-07-02 06:41:17.880         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.880         # identical
2025-07-02 06:41:17.880
2025-07-02 06:41:17.880         # pump out diffs from before the synch point
2025-07-02 06:41:17.880         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.880
2025-07-02 06:41:17.880         # do intraline marking on the synch pair
2025-07-02 06:41:17.880         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.880         if eqi is None:
2025-07-02 06:41:17.880             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.880             atags = btags = ""
2025-07-02 06:41:17.880             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.880             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.880                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.880                 if tag == 'replace':
2025-07-02 06:41:17.880                     atags += '^' * la
2025-07-02 06:41:17.880                     btags += '^' * lb
2025-07-02 06:41:17.880                 elif tag == 'delete':
2025-07-02 06:41:17.880                     atags += '-' * la
2025-07-02 06:41:17.881                 elif tag == 'insert':
2025-07-02 06:41:17.881                     btags += '+' * lb
2025-07-02 06:41:17.881                 elif tag == 'equal':
2025-07-02 06:41:17.881                     atags += ' ' * la
2025-07-02 06:41:17.881                     btags += ' ' * lb
2025-07-02 06:41:17.881                 else:
2025-07-02 06:41:17.881                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.881             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.881         else:
2025-07-02 06:41:17.881             # the synch pair is identical
2025-07-02 06:41:17.881             yield '  ' + aelt
2025-07-02 06:41:17.881
2025-07-02 06:41:17.881         # pump out diffs from after the synch point
2025-07-02 06:41:17.881 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.881
2025-07-02 06:41:17.881 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.881 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.881
2025-07-02 06:41:17.881 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.882 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.882 alo = 305, ahi = 1101
2025-07-02 06:41:17.882 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.882 blo = 305, bhi = 1101
2025-07-02 06:41:17.882
2025-07-02 06:41:17.882     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.882         g = []
2025-07-02 06:41:17.882         if alo < ahi:
2025-07-02 06:41:17.882             if blo < bhi:
2025-07-02 06:41:17.882                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.882             else:
2025-07-02 06:41:17.882                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.882         elif blo < bhi:
2025-07-02 06:41:17.882             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.882
2025-07-02 06:41:17.882 >       yield from g
2025-07-02 06:41:17.882
2025-07-02 06:41:17.882 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.882 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.882
2025-07-02 06:41:17.883 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.883 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.883 alo = 305, ahi = 1101
2025-07-02 06:41:17.883 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.883 blo = 305, bhi = 1101
2025-07-02 06:41:17.883
2025-07-02 06:41:17.883     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.883         r"""
2025-07-02 06:41:17.883         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.883         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.883         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.883         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.883
2025-07-02 06:41:17.883         Example:
2025-07-02 06:41:17.883
2025-07-02 06:41:17.883         >>> d = Differ()
2025-07-02 06:41:17.883         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.883         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.883         >>> print(''.join(results), end="")
2025-07-02 06:41:17.884         - abcDefghiJkl
2025-07-02 06:41:17.884         + abcdefGhijkl
2025-07-02 06:41:17.884         """
2025-07-02 06:41:17.884
2025-07-02 06:41:17.884         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.884         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.884         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.884         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.884         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.884
2025-07-02 06:41:17.884         # search for the pair that matches best without being identical
2025-07-02 06:41:17.884         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.884         # on junk -- unless we have to)
2025-07-02 06:41:17.884         for j in range(blo, bhi):
2025-07-02 06:41:17.884             bj = b[j]
2025-07-02 06:41:17.884             cruncher.set_seq2(bj)
2025-07-02 06:41:17.885             for i in range(alo, ahi):
2025-07-02 06:41:17.885                 ai = a[i]
2025-07-02 06:41:17.885                 if ai == bj:
2025-07-02 06:41:17.885                     if eqi is None:
2025-07-02 06:41:17.885                         eqi, eqj = i, j
2025-07-02 06:41:17.885                     continue
2025-07-02 06:41:17.885                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.885                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.885                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.885                 # compares by a factor of 3.
2025-07-02 06:41:17.885                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.885                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.885                 # of the computation is cached by cruncher
2025-07-02 06:41:17.885                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.885                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.885                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.885                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.885         if best_ratio < cutoff:
2025-07-02 06:41:17.886             # no non-identical "pretty close" pair
2025-07-02 06:41:17.886             if eqi is None:
2025-07-02 06:41:17.886                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.886                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.886                 return
2025-07-02 06:41:17.886             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.886             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.886         else:
2025-07-02 06:41:17.886             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.886             eqi = None
2025-07-02 06:41:17.886
2025-07-02 06:41:17.886         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.886         # identical
2025-07-02 06:41:17.886
2025-07-02 06:41:17.886         # pump out diffs from before the synch point
2025-07-02 06:41:17.886         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.886
2025-07-02 06:41:17.886         # do intraline marking on the synch pair
2025-07-02 06:41:17.886         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.887         if eqi is None:
2025-07-02 06:41:17.887             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.887             atags = btags = ""
2025-07-02 06:41:17.887             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.887             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.887                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.887                 if tag == 'replace':
2025-07-02 06:41:17.887                     atags += '^' * la
2025-07-02 06:41:17.887                     btags += '^' * lb
2025-07-02 06:41:17.887                 elif tag == 'delete':
2025-07-02 06:41:17.887                     atags += '-' * la
2025-07-02 06:41:17.887                 elif tag == 'insert':
2025-07-02 06:41:17.887                     btags += '+' * lb
2025-07-02 06:41:17.887                 elif tag == 'equal':
2025-07-02 06:41:17.887                     atags += ' ' * la
2025-07-02 06:41:17.887                     btags += ' ' * lb
2025-07-02 06:41:17.887                 else:
2025-07-02 06:41:17.887                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.887             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.888         else:
2025-07-02 06:41:17.888             # the synch pair is identical
2025-07-02 06:41:17.888             yield '  ' + aelt
2025-07-02 06:41:17.888
2025-07-02 06:41:17.888         # pump out diffs from after the synch point
2025-07-02 06:41:17.888 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.888
2025-07-02 06:41:17.888 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.888 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.888
2025-07-02 06:41:17.888 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.888 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.888 alo = 306, ahi = 1101
2025-07-02 06:41:17.888 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.888 blo = 306, bhi = 1101
2025-07-02 06:41:17.888
2025-07-02 06:41:17.888     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.888         g = []
2025-07-02 06:41:17.888         if alo < ahi:
2025-07-02 06:41:17.889             if blo < bhi:
2025-07-02 06:41:17.889                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.889             else:
2025-07-02 06:41:17.889                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.889         elif blo < bhi:
2025-07-02 06:41:17.889             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.889
2025-07-02 06:41:17.889 >       yield from g
2025-07-02 06:41:17.889
2025-07-02 06:41:17.889 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.889 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.889
2025-07-02 06:41:17.889 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.889 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.889 alo = 306, ahi = 1101
2025-07-02 06:41:17.889 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.889 blo = 306, bhi = 1101
2025-07-02 06:41:17.889
2025-07-02 06:41:17.889     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.889         r"""
2025-07-02 06:41:17.890         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.890         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.890         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.890         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.890
2025-07-02 06:41:17.890         Example:
2025-07-02 06:41:17.890
2025-07-02 06:41:17.890         >>> d = Differ()
2025-07-02 06:41:17.890         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.890         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.890         >>> print(''.join(results), end="")
2025-07-02 06:41:17.890         - abcDefghiJkl
2025-07-02 06:41:17.890         + abcdefGhijkl
2025-07-02 06:41:17.890         """
2025-07-02 06:41:17.890
2025-07-02 06:41:17.890         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.890         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.891         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.891         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.891         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.891
2025-07-02 06:41:17.891         # search for the pair that matches best without being identical
2025-07-02 06:41:17.891         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.891         # on junk -- unless we have to)
2025-07-02 06:41:17.891         for j in range(blo, bhi):
2025-07-02 06:41:17.891             bj = b[j]
2025-07-02 06:41:17.891             cruncher.set_seq2(bj)
2025-07-02 06:41:17.891             for i in range(alo, ahi):
2025-07-02 06:41:17.891                 ai = a[i]
2025-07-02 06:41:17.891                 if ai == bj:
2025-07-02 06:41:17.891                     if eqi is None:
2025-07-02 06:41:17.891                         eqi, eqj = i, j
2025-07-02 06:41:17.891                     continue
2025-07-02 06:41:17.891                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.891                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.891                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.892                 # compares by a factor of 3.
2025-07-02 06:41:17.892                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.892                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.892                 # of the computation is cached by cruncher
2025-07-02 06:41:17.892                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.892                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.892                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.892                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.892         if best_ratio < cutoff:
2025-07-02 06:41:17.892             # no non-identical "pretty close" pair
2025-07-02 06:41:17.892             if eqi is None:
2025-07-02 06:41:17.892                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.892                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.892                 return
2025-07-02 06:41:17.892             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.892             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.892         else:
2025-07-02 06:41:17.892             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.892             eqi = None
2025-07-02 06:41:17.892
2025-07-02 06:41:17.893         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.893         # identical
2025-07-02 06:41:17.893
2025-07-02 06:41:17.893         # pump out diffs from before the synch point
2025-07-02 06:41:17.893         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.893
2025-07-02 06:41:17.893         # do intraline marking on the synch pair
2025-07-02 06:41:17.893         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.893         if eqi is None:
2025-07-02 06:41:17.893             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.893             atags = btags = ""
2025-07-02 06:41:17.893             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.893             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.893                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.893                 if tag == 'replace':
2025-07-02 06:41:17.893                     atags += '^' * la
2025-07-02 06:41:17.893                     btags += '^' * lb
2025-07-02 06:41:17.893                 elif tag == 'delete':
2025-07-02 06:41:17.893                     atags += '-' * la
2025-07-02 06:41:17.894                 elif tag == 'insert':
2025-07-02 06:41:17.894                     btags += '+' * lb
2025-07-02 06:41:17.894                 elif tag == 'equal':
2025-07-02 06:41:17.894                     atags += ' ' * la
2025-07-02 06:41:17.894                     btags += ' ' * lb
2025-07-02 06:41:17.894                 else:
2025-07-02 06:41:17.894                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.894             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.894         else:
2025-07-02 06:41:17.894             # the synch pair is identical
2025-07-02 06:41:17.894             yield '  ' + aelt
2025-07-02 06:41:17.894
2025-07-02 06:41:17.894         # pump out diffs from after the synch point
2025-07-02 06:41:17.894 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.894
2025-07-02 06:41:17.894 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.894 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.894
2025-07-02 06:41:17.894 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.895 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.895 alo = 307, ahi = 1101
2025-07-02 06:41:17.895 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.895 blo = 307, bhi = 1101
2025-07-02 06:41:17.895
2025-07-02 06:41:17.895     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.895         g = []
2025-07-02 06:41:17.895         if alo < ahi:
2025-07-02 06:41:17.895             if blo < bhi:
2025-07-02 06:41:17.895                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.895             else:
2025-07-02 06:41:17.895                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.895         elif blo < bhi:
2025-07-02 06:41:17.895             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.895
2025-07-02 06:41:17.895 >       yield from g
2025-07-02 06:41:17.895
2025-07-02 06:41:17.895 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.896 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.896
2025-07-02 06:41:17.896 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.896 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.896 alo = 307, ahi = 1101
2025-07-02 06:41:17.896 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.896 blo = 307, bhi = 1101
2025-07-02 06:41:17.896
2025-07-02 06:41:17.896     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.896         r"""
2025-07-02 06:41:17.896         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.896         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.896         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.896         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.896
2025-07-02 06:41:17.896         Example:
2025-07-02 06:41:17.896
2025-07-02 06:41:17.896         >>> d = Differ()
2025-07-02 06:41:17.896         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.897         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.897         >>> print(''.join(results), end="")
2025-07-02 06:41:17.897         - abcDefghiJkl
2025-07-02 06:41:17.897         + abcdefGhijkl
2025-07-02 06:41:17.897         """
2025-07-02 06:41:17.897
2025-07-02 06:41:17.897         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.897         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.897         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.897         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.897         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.897
2025-07-02 06:41:17.897         # search for the pair that matches best without being identical
2025-07-02 06:41:17.897         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.897         # on junk -- unless we have to)
2025-07-02 06:41:17.897         for j in range(blo, bhi):
2025-07-02 06:41:17.897             bj = b[j]
2025-07-02 06:41:17.897             cruncher.set_seq2(bj)
2025-07-02 06:41:17.898             for i in range(alo, ahi):
2025-07-02 06:41:17.898                 ai = a[i]
2025-07-02 06:41:17.898                 if ai == bj:
2025-07-02 06:41:17.898                     if eqi is None:
2025-07-02 06:41:17.898                         eqi, eqj = i, j
2025-07-02 06:41:17.898                     continue
2025-07-02 06:41:17.898                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.898                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.898                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.898                 # compares by a factor of 3.
2025-07-02 06:41:17.898                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.898                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.898                 # of the computation is cached by cruncher
2025-07-02 06:41:17.898                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.898                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.898                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.898                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.898         if best_ratio < cutoff:
2025-07-02 06:41:17.898             # no non-identical "pretty close" pair
2025-07-02 06:41:17.899             if eqi is None:
2025-07-02 06:41:17.899                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.899                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.899                 return
2025-07-02 06:41:17.899             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.899             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.899         else:
2025-07-02 06:41:17.899             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.899             eqi = None
2025-07-02 06:41:17.899
2025-07-02 06:41:17.899         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.899         # identical
2025-07-02 06:41:17.899
2025-07-02 06:41:17.899         # pump out diffs from before the synch point
2025-07-02 06:41:17.899         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.899
2025-07-02 06:41:17.899         # do intraline marking on the synch pair
2025-07-02 06:41:17.899         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.900         if eqi is None:
2025-07-02 06:41:17.900             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.900             atags = btags = ""
2025-07-02 06:41:17.900             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.900             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.900                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.900                 if tag == 'replace':
2025-07-02 06:41:17.900                     atags += '^' * la
2025-07-02 06:41:17.900                     btags += '^' * lb
2025-07-02 06:41:17.900                 elif tag == 'delete':
2025-07-02 06:41:17.900                     atags += '-' * la
2025-07-02 06:41:17.900                 elif tag == 'insert':
2025-07-02 06:41:17.900                     btags += '+' * lb
2025-07-02 06:41:17.900                 elif tag == 'equal':
2025-07-02 06:41:17.900                     atags += ' ' * la
2025-07-02 06:41:17.900                     btags += ' ' * lb
2025-07-02 06:41:17.900                 else:
2025-07-02 06:41:17.900                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.901             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.901         else:
2025-07-02 06:41:17.901             # the synch pair is identical
2025-07-02 06:41:17.901             yield '  ' + aelt
2025-07-02 06:41:17.901
2025-07-02 06:41:17.901         # pump out diffs from after the synch point
2025-07-02 06:41:17.901 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.901
2025-07-02 06:41:17.901 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.901 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.901
2025-07-02 06:41:17.901 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.901 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.901 alo = 308, ahi = 1101
2025-07-02 06:41:17.901 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.901 blo = 308, bhi = 1101
2025-07-02 06:41:17.901
2025-07-02 06:41:17.901     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.902         g = []
2025-07-02 06:41:17.902         if alo < ahi:
2025-07-02 06:41:17.902             if blo < bhi:
2025-07-02 06:41:17.902                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.902             else:
2025-07-02 06:41:17.902                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.902         elif blo < bhi:
2025-07-02 06:41:17.902             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.902
2025-07-02 06:41:17.902 >       yield from g
2025-07-02 06:41:17.902
2025-07-02 06:41:17.902 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.902 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.902
2025-07-02 06:41:17.902 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.902 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.902 alo = 308, ahi = 1101
2025-07-02 06:41:17.903 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.903 blo = 308, bhi = 1101
2025-07-02 06:41:17.903
2025-07-02 06:41:17.903     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.903         r"""
2025-07-02 06:41:17.903         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.903         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.903         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.903         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.903
2025-07-02 06:41:17.903         Example:
2025-07-02 06:41:17.903
2025-07-02 06:41:17.903         >>> d = Differ()
2025-07-02 06:41:17.903         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.903         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.903         >>> print(''.join(results), end="")
2025-07-02 06:41:17.903         - abcDefghiJkl
2025-07-02 06:41:17.904         + abcdefGhijkl
2025-07-02 06:41:17.904         """
2025-07-02 06:41:17.904
2025-07-02 06:41:17.904         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.904         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.904         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.904         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.904         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.904
2025-07-02 06:41:17.904         # search for the pair that matches best without being identical
2025-07-02 06:41:17.904         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.904         # on junk -- unless we have to)
2025-07-02 06:41:17.904         for j in range(blo, bhi):
2025-07-02 06:41:17.904             bj = b[j]
2025-07-02 06:41:17.904             cruncher.set_seq2(bj)
2025-07-02 06:41:17.904             for i in range(alo, ahi):
2025-07-02 06:41:17.904                 ai = a[i]
2025-07-02 06:41:17.905                 if ai == bj:
2025-07-02 06:41:17.905                     if eqi is None:
2025-07-02 06:41:17.905                         eqi, eqj = i, j
2025-07-02 06:41:17.905                     continue
2025-07-02 06:41:17.905                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.905                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.905                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.905                 # compares by a factor of 3.
2025-07-02 06:41:17.905                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.905                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.905                 # of the computation is cached by cruncher
2025-07-02 06:41:17.905                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.905                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.905                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.905                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.905         if best_ratio < cutoff:
2025-07-02 06:41:17.905             # no non-identical "pretty close" pair
2025-07-02 06:41:17.905             if eqi is None:
2025-07-02 06:41:17.906                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.906                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.906                 return
2025-07-02 06:41:17.906             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.906             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.906         else:
2025-07-02 06:41:17.906             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.906             eqi = None
2025-07-02 06:41:17.906
2025-07-02 06:41:17.906         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.906         # identical
2025-07-02 06:41:17.906
2025-07-02 06:41:17.906         # pump out diffs from before the synch point
2025-07-02 06:41:17.906         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.906
2025-07-02 06:41:17.906         # do intraline marking on the synch pair
2025-07-02 06:41:17.906         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.906         if eqi is None:
2025-07-02 06:41:17.906             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.907             atags = btags = ""
2025-07-02 06:41:17.907             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.907             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.907                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.907                 if tag == 'replace':
2025-07-02 06:41:17.907                     atags += '^' * la
2025-07-02 06:41:17.907                     btags += '^' * lb
2025-07-02 06:41:17.907                 elif tag == 'delete':
2025-07-02 06:41:17.907                     atags += '-' * la
2025-07-02 06:41:17.907                 elif tag == 'insert':
2025-07-02 06:41:17.907                     btags += '+' * lb
2025-07-02 06:41:17.907                 elif tag == 'equal':
2025-07-02 06:41:17.907                     atags += ' ' * la
2025-07-02 06:41:17.907                     btags += ' ' * lb
2025-07-02 06:41:17.907                 else:
2025-07-02 06:41:17.907                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.907             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.907         else:
2025-07-02 06:41:17.907             # the synch pair is identical
2025-07-02 06:41:17.908             yield '  ' + aelt
2025-07-02 06:41:17.908
2025-07-02 06:41:17.908         # pump out diffs from after the synch point
2025-07-02 06:41:17.908 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.908
2025-07-02 06:41:17.908 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.908 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.908
2025-07-02 06:41:17.908 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.908 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.908 alo = 309, ahi = 1101
2025-07-02 06:41:17.908 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.908 blo = 309, bhi = 1101
2025-07-02 06:41:17.908
2025-07-02 06:41:17.908     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.908         g = []
2025-07-02 06:41:17.908         if alo < ahi:
2025-07-02 06:41:17.908             if blo < bhi:
2025-07-02 06:41:17.909                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.909             else:
2025-07-02 06:41:17.909                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.909         elif blo < bhi:
2025-07-02 06:41:17.909             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.909
2025-07-02 06:41:17.909 >       yield from g
2025-07-02 06:41:17.909
2025-07-02 06:41:17.909 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.909 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.909
2025-07-02 06:41:17.909 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.909 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.909 alo = 309, ahi = 1101
2025-07-02 06:41:17.909 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.909 blo = 309, bhi = 1101
2025-07-02 06:41:17.909
2025-07-02 06:41:17.909     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.909         r"""
2025-07-02 06:41:17.910         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.910         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.910         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.910         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.910
2025-07-02 06:41:17.910         Example:
2025-07-02 06:41:17.910
2025-07-02 06:41:17.910         >>> d = Differ()
2025-07-02 06:41:17.910         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.910         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.910         >>> print(''.join(results), end="")
2025-07-02 06:41:17.910         - abcDefghiJkl
2025-07-02 06:41:17.910         + abcdefGhijkl
2025-07-02 06:41:17.910         """
2025-07-02 06:41:17.910
2025-07-02 06:41:17.910         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.911         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.911         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.911         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.911         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.911
2025-07-02 06:41:17.911         # search for the pair that matches best without being identical
2025-07-02 06:41:17.911         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.911         # on junk -- unless we have to)
2025-07-02 06:41:17.911         for j in range(blo, bhi):
2025-07-02 06:41:17.911             bj = b[j]
2025-07-02 06:41:17.911             cruncher.set_seq2(bj)
2025-07-02 06:41:17.911             for i in range(alo, ahi):
2025-07-02 06:41:17.911                 ai = a[i]
2025-07-02 06:41:17.911                 if ai == bj:
2025-07-02 06:41:17.911                     if eqi is None:
2025-07-02 06:41:17.911                         eqi, eqj = i, j
2025-07-02 06:41:17.911                     continue
2025-07-02 06:41:17.911                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.911                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.912                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.912                 # compares by a factor of 3.
2025-07-02 06:41:17.912                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.912                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.912                 # of the computation is cached by cruncher
2025-07-02 06:41:17.912                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.912                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.912                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.912                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.912         if best_ratio < cutoff:
2025-07-02 06:41:17.912             # no non-identical "pretty close" pair
2025-07-02 06:41:17.912             if eqi is None:
2025-07-02 06:41:17.912                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.912                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.912                 return
2025-07-02 06:41:17.912             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.912             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.912         else:
2025-07-02 06:41:17.913             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.913             eqi = None
2025-07-02 06:41:17.913
2025-07-02 06:41:17.913         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.913         # identical
2025-07-02 06:41:17.913
2025-07-02 06:41:17.913         # pump out diffs from before the synch point
2025-07-02 06:41:17.913         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.913
2025-07-02 06:41:17.913         # do intraline marking on the synch pair
2025-07-02 06:41:17.913         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.913         if eqi is None:
2025-07-02 06:41:17.913             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.913             atags = btags = ""
2025-07-02 06:41:17.913             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.913             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.913                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.913                 if tag == 'replace':
2025-07-02 06:41:17.914                     atags += '^' * la
2025-07-02 06:41:17.914                     btags += '^' * lb
2025-07-02 06:41:17.914                 elif tag == 'delete':
2025-07-02 06:41:17.914                     atags += '-' * la
2025-07-02 06:41:17.914                 elif tag == 'insert':
2025-07-02 06:41:17.914                     btags += '+' * lb
2025-07-02 06:41:17.914                 elif tag == 'equal':
2025-07-02 06:41:17.914                     atags += ' ' * la
2025-07-02 06:41:17.914                     btags += ' ' * lb
2025-07-02 06:41:17.914                 else:
2025-07-02 06:41:17.914                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.914             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.914         else:
2025-07-02 06:41:17.914             # the synch pair is identical
2025-07-02 06:41:17.914             yield '  ' + aelt
2025-07-02 06:41:17.914
2025-07-02 06:41:17.914         # pump out diffs from after the synch point
2025-07-02 06:41:17.914 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.914
2025-07-02 06:41:17.915 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.915 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.915
2025-07-02 06:41:17.915 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.915 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.915 alo = 312, ahi = 1101
2025-07-02 06:41:17.915 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.915 blo = 312, bhi = 1101
2025-07-02 06:41:17.915
2025-07-02 06:41:17.915     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.915         g = []
2025-07-02 06:41:17.915         if alo < ahi:
2025-07-02 06:41:17.915             if blo < bhi:
2025-07-02 06:41:17.915                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.915             else:
2025-07-02 06:41:17.915                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.915         elif blo < bhi:
2025-07-02 06:41:17.916             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.916
2025-07-02 06:41:17.916 >       yield from g
2025-07-02 06:41:17.916
2025-07-02 06:41:17.916 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.916 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.916
2025-07-02 06:41:17.916 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.916 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.916 alo = 312, ahi = 1101
2025-07-02 06:41:17.916 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.916 blo = 312, bhi = 1101
2025-07-02 06:41:17.916
2025-07-02 06:41:17.916     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.916         r"""
2025-07-02 06:41:17.916         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.916         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.916         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.917         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.917
2025-07-02 06:41:17.917         Example:
2025-07-02 06:41:17.917
2025-07-02 06:41:17.917         >>> d = Differ()
2025-07-02 06:41:17.917         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.917         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.917         >>> print(''.join(results), end="")
2025-07-02 06:41:17.917         - abcDefghiJkl
2025-07-02 06:41:17.917         + abcdefGhijkl
2025-07-02 06:41:17.917         """
2025-07-02 06:41:17.917
2025-07-02 06:41:17.917         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.917         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.917         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.917         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.917         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.918
2025-07-02 06:41:17.918         # search for the pair that matches best without being identical
2025-07-02 06:41:17.918         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.918         # on junk -- unless we have to)
2025-07-02 06:41:17.918         for j in range(blo, bhi):
2025-07-02 06:41:17.918             bj = b[j]
2025-07-02 06:41:17.918             cruncher.set_seq2(bj)
2025-07-02 06:41:17.918             for i in range(alo, ahi):
2025-07-02 06:41:17.918                 ai = a[i]
2025-07-02 06:41:17.918                 if ai == bj:
2025-07-02 06:41:17.918                     if eqi is None:
2025-07-02 06:41:17.918                         eqi, eqj = i, j
2025-07-02 06:41:17.918                     continue
2025-07-02 06:41:17.918                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.918                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.918                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.918                 # compares by a factor of 3.
2025-07-02 06:41:17.918                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.919                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.919                 # of the computation is cached by cruncher
2025-07-02 06:41:17.919                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.919                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.919                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.919                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.919         if best_ratio < cutoff:
2025-07-02 06:41:17.919             # no non-identical "pretty close" pair
2025-07-02 06:41:17.919             if eqi is None:
2025-07-02 06:41:17.919                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.919                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.919                 return
2025-07-02 06:41:17.919             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.919             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.919         else:
2025-07-02 06:41:17.919             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.919             eqi = None
2025-07-02 06:41:17.919
2025-07-02 06:41:17.919         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.920         # identical
2025-07-02 06:41:17.920
2025-07-02 06:41:17.920         # pump out diffs from before the synch point
2025-07-02 06:41:17.920         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.920
2025-07-02 06:41:17.920         # do intraline marking on the synch pair
2025-07-02 06:41:17.920         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.920         if eqi is None:
2025-07-02 06:41:17.920             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.920             atags = btags = ""
2025-07-02 06:41:17.920             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.920             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.920                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.920                 if tag == 'replace':
2025-07-02 06:41:17.920                     atags += '^' * la
2025-07-02 06:41:17.920                     btags += '^' * lb
2025-07-02 06:41:17.920                 elif tag == 'delete':
2025-07-02 06:41:17.920                     atags += '-' * la
2025-07-02 06:41:17.920                 elif tag == 'insert':
2025-07-02 06:41:17.921                     btags += '+' * lb
2025-07-02 06:41:17.921                 elif tag == 'equal':
2025-07-02 06:41:17.921                     atags += ' ' * la
2025-07-02 06:41:17.921                     btags += ' ' * lb
2025-07-02 06:41:17.921                 else:
2025-07-02 06:41:17.921                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.921             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.921         else:
2025-07-02 06:41:17.921             # the synch pair is identical
2025-07-02 06:41:17.921             yield '  ' + aelt
2025-07-02 06:41:17.921
2025-07-02 06:41:17.921         # pump out diffs from after the synch point
2025-07-02 06:41:17.921 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.921
2025-07-02 06:41:17.921 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.921 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.921
2025-07-02 06:41:17.921 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.922 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.922 alo = 313, ahi = 1101
2025-07-02 06:41:17.922 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.922 blo = 313, bhi = 1101
2025-07-02 06:41:17.922
2025-07-02 06:41:17.922     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.922         g = []
2025-07-02 06:41:17.922         if alo < ahi:
2025-07-02 06:41:17.922             if blo < bhi:
2025-07-02 06:41:17.922                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.922             else:
2025-07-02 06:41:17.922                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.922         elif blo < bhi:
2025-07-02 06:41:17.922             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.922
2025-07-02 06:41:17.922 >       yield from g
2025-07-02 06:41:17.922
2025-07-02 06:41:17.922 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.923 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.923
2025-07-02 06:41:17.923 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.923 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.923 alo = 313, ahi = 1101
2025-07-02 06:41:17.923 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.923 blo = 313, bhi = 1101
2025-07-02 06:41:17.923
2025-07-02 06:41:17.923     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.923         r"""
2025-07-02 06:41:17.923         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.923         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.923         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.923         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.923
2025-07-02 06:41:17.923         Example:
2025-07-02 06:41:17.923
2025-07-02 06:41:17.923         >>> d = Differ()
2025-07-02 06:41:17.924         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.924         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.924         >>> print(''.join(results), end="")
2025-07-02 06:41:17.924         - abcDefghiJkl
2025-07-02 06:41:17.924         + abcdefGhijkl
2025-07-02 06:41:17.924         """
2025-07-02 06:41:17.924
2025-07-02 06:41:17.924         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.924         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.924         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.924         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.924         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.924
2025-07-02 06:41:17.924         # search for the pair that matches best without being identical
2025-07-02 06:41:17.924         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.924         # on junk -- unless we have to)
2025-07-02 06:41:17.924         for j in range(blo, bhi):
2025-07-02 06:41:17.925             bj = b[j]
2025-07-02 06:41:17.925             cruncher.set_seq2(bj)
2025-07-02 06:41:17.925             for i in range(alo, ahi):
2025-07-02 06:41:17.925                 ai = a[i]
2025-07-02 06:41:17.925                 if ai == bj:
2025-07-02 06:41:17.925                     if eqi is None:
2025-07-02 06:41:17.925                         eqi, eqj = i, j
2025-07-02 06:41:17.925                     continue
2025-07-02 06:41:17.925                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.925                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.925                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.925                 # compares by a factor of 3.
2025-07-02 06:41:17.925                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.925                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.925                 # of the computation is cached by cruncher
2025-07-02 06:41:17.925                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.925                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.925                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.925                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.925         if best_ratio < cutoff:
2025-07-02 06:41:17.926             # no non-identical "pretty close" pair
2025-07-02 06:41:17.926             if eqi is None:
2025-07-02 06:41:17.926                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.926                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.926                 return
2025-07-02 06:41:17.926             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.926             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.926         else:
2025-07-02 06:41:17.926             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.926             eqi = None
2025-07-02 06:41:17.926
2025-07-02 06:41:17.926         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.926         # identical
2025-07-02 06:41:17.926
2025-07-02 06:41:17.926         # pump out diffs from before the synch point
2025-07-02 06:41:17.926         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.926
2025-07-02 06:41:17.926         # do intraline marking on the synch pair
2025-07-02 06:41:17.926         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.927         if eqi is None:
2025-07-02 06:41:17.927             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.927             atags = btags = ""
2025-07-02 06:41:17.927             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.927             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.927                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.927                 if tag == 'replace':
2025-07-02 06:41:17.927                     atags += '^' * la
2025-07-02 06:41:17.927                     btags += '^' * lb
2025-07-02 06:41:17.927                 elif tag == 'delete':
2025-07-02 06:41:17.927                     atags += '-' * la
2025-07-02 06:41:17.927                 elif tag == 'insert':
2025-07-02 06:41:17.927                     btags += '+' * lb
2025-07-02 06:41:17.927                 elif tag == 'equal':
2025-07-02 06:41:17.927                     atags += ' ' * la
2025-07-02 06:41:17.927                     btags += ' ' * lb
2025-07-02 06:41:17.927                 else:
2025-07-02 06:41:17.927                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.927             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.927         else:
2025-07-02 06:41:17.928             # the synch pair is identical
2025-07-02 06:41:17.928             yield '  ' + aelt
2025-07-02 06:41:17.928
2025-07-02 06:41:17.928         # pump out diffs from after the synch point
2025-07-02 06:41:17.928 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.928
2025-07-02 06:41:17.928 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.928 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.928
2025-07-02 06:41:17.928 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.928 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.928 alo = 314, ahi = 1101
2025-07-02 06:41:17.928 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.928 blo = 314, bhi = 1101
2025-07-02 06:41:17.928
2025-07-02 06:41:17.928     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.928         g = []
2025-07-02 06:41:17.928         if alo < ahi:
2025-07-02 06:41:17.928             if blo < bhi:
2025-07-02 06:41:17.929                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.929             else:
2025-07-02 06:41:17.929                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.929         elif blo < bhi:
2025-07-02 06:41:17.929             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.929
2025-07-02 06:41:17.929 >       yield from g
2025-07-02 06:41:17.929
2025-07-02 06:41:17.929 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.929 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.929
2025-07-02 06:41:17.929 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.929 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.929 alo = 314, ahi = 1101
2025-07-02 06:41:17.929 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.929 blo = 314, bhi = 1101
2025-07-02 06:41:17.929
2025-07-02 06:41:17.929     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.929         r"""
2025-07-02 06:41:17.930         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.930         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.930         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.930         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.930
2025-07-02 06:41:17.930         Example:
2025-07-02 06:41:17.930
2025-07-02 06:41:17.930         >>> d = Differ()
2025-07-02 06:41:17.930         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.930         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.930         >>> print(''.join(results), end="")
2025-07-02 06:41:17.930         - abcDefghiJkl
2025-07-02 06:41:17.930         + abcdefGhijkl
2025-07-02 06:41:17.930         """
2025-07-02 06:41:17.930
2025-07-02 06:41:17.930         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.930         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.930         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.931         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.931         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.931
2025-07-02 06:41:17.931         # search for the pair that matches best without being identical
2025-07-02 06:41:17.931         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.931         # on junk -- unless we have to)
2025-07-02 06:41:17.931         for j in range(blo, bhi):
2025-07-02 06:41:17.931             bj = b[j]
2025-07-02 06:41:17.931             cruncher.set_seq2(bj)
2025-07-02 06:41:17.931             for i in range(alo, ahi):
2025-07-02 06:41:17.931                 ai = a[i]
2025-07-02 06:41:17.931                 if ai == bj:
2025-07-02 06:41:17.931                     if eqi is None:
2025-07-02 06:41:17.931                         eqi, eqj = i, j
2025-07-02 06:41:17.931                     continue
2025-07-02 06:41:17.931                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.931                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.931                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.932                 # compares by a factor of 3.
2025-07-02 06:41:17.932                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.932                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.932                 # of the computation is cached by cruncher
2025-07-02 06:41:17.932                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.932                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.932                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.932                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.932         if best_ratio < cutoff:
2025-07-02 06:41:17.932             # no non-identical "pretty close" pair
2025-07-02 06:41:17.932             if eqi is None:
2025-07-02 06:41:17.932                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.932                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.932                 return
2025-07-02 06:41:17.932             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.932             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.932         else:
2025-07-02 06:41:17.932             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.933             eqi = None
2025-07-02 06:41:17.933
2025-07-02 06:41:17.933         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.933         # identical
2025-07-02 06:41:17.933
2025-07-02 06:41:17.933         # pump out diffs from before the synch point
2025-07-02 06:41:17.933         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.933
2025-07-02 06:41:17.933         # do intraline marking on the synch pair
2025-07-02 06:41:17.933         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.933         if eqi is None:
2025-07-02 06:41:17.933             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.933             atags = btags = ""
2025-07-02 06:41:17.933             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.933             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.933                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.933                 if tag == 'replace':
2025-07-02 06:41:17.933                     atags += '^' * la
2025-07-02 06:41:17.933                     btags += '^' * lb
2025-07-02 06:41:17.934                 elif tag == 'delete':
2025-07-02 06:41:17.934                     atags += '-' * la
2025-07-02 06:41:17.934                 elif tag == 'insert':
2025-07-02 06:41:17.934                     btags += '+' * lb
2025-07-02 06:41:17.934                 elif tag == 'equal':
2025-07-02 06:41:17.934                     atags += ' ' * la
2025-07-02 06:41:17.934                     btags += ' ' * lb
2025-07-02 06:41:17.934                 else:
2025-07-02 06:41:17.934                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.934             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.934         else:
2025-07-02 06:41:17.934             # the synch pair is identical
2025-07-02 06:41:17.934             yield '  ' + aelt
2025-07-02 06:41:17.934
2025-07-02 06:41:17.934         # pump out diffs from after the synch point
2025-07-02 06:41:17.934 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.934
2025-07-02 06:41:17.934 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.934 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.934
2025-07-02 06:41:17.935 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.935 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.935 alo = 315, ahi = 1101
2025-07-02 06:41:17.935 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.935 blo = 315, bhi = 1101
2025-07-02 06:41:17.935
2025-07-02 06:41:17.935     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.935         g = []
2025-07-02 06:41:17.935         if alo < ahi:
2025-07-02 06:41:17.935             if blo < bhi:
2025-07-02 06:41:17.935                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.935             else:
2025-07-02 06:41:17.935                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.935         elif blo < bhi:
2025-07-02 06:41:17.935             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.935
2025-07-02 06:41:17.935 >       yield from g
2025-07-02 06:41:17.935
2025-07-02 06:41:17.935 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.936 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.936
2025-07-02 06:41:17.936 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.936 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.936 alo = 315, ahi = 1101
2025-07-02 06:41:17.936 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.936 blo = 315, bhi = 1101
2025-07-02 06:41:17.936
2025-07-02 06:41:17.936     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.936         r"""
2025-07-02 06:41:17.936         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.936         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.936         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.936         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.936
2025-07-02 06:41:17.936         Example:
2025-07-02 06:41:17.936
2025-07-02 06:41:17.936         >>> d = Differ()
2025-07-02 06:41:17.937         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.937         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.937         >>> print(''.join(results), end="")
2025-07-02 06:41:17.937         - abcDefghiJkl
2025-07-02 06:41:17.937         + abcdefGhijkl
2025-07-02 06:41:17.937         """
2025-07-02 06:41:17.937
2025-07-02 06:41:17.937         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.937         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.937         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.937         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.937         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.937
2025-07-02 06:41:17.937         # search for the pair that matches best without being identical
2025-07-02 06:41:17.937         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.937         # on junk -- unless we have to)
2025-07-02 06:41:17.937         for j in range(blo, bhi):
2025-07-02 06:41:17.937             bj = b[j]
2025-07-02 06:41:17.938             cruncher.set_seq2(bj)
2025-07-02 06:41:17.938             for i in range(alo, ahi):
2025-07-02 06:41:17.938                 ai = a[i]
2025-07-02 06:41:17.938                 if ai == bj:
2025-07-02 06:41:17.938                     if eqi is None:
2025-07-02 06:41:17.938                         eqi, eqj = i, j
2025-07-02 06:41:17.938                     continue
2025-07-02 06:41:17.938                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.938                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.938                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.938                 # compares by a factor of 3.
2025-07-02 06:41:17.938                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.938                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.938                 # of the computation is cached by cruncher
2025-07-02 06:41:17.938                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.938                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.938                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.938                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.938         if best_ratio < cutoff:
2025-07-02 06:41:17.938             # no non-identical "pretty close" pair
2025-07-02 06:41:17.939             if eqi is None:
2025-07-02 06:41:17.939                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.939                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.939                 return
2025-07-02 06:41:17.939             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.939             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.939         else:
2025-07-02 06:41:17.939             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.939             eqi = None
2025-07-02 06:41:17.939
2025-07-02 06:41:17.939         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.939         # identical
2025-07-02 06:41:17.939
2025-07-02 06:41:17.939         # pump out diffs from before the synch point
2025-07-02 06:41:17.939         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.939
2025-07-02 06:41:17.939         # do intraline marking on the synch pair
2025-07-02 06:41:17.939         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.940         if eqi is None:
2025-07-02 06:41:17.940             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.940             atags = btags = ""
2025-07-02 06:41:17.940             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.940             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.940                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.940                 if tag == 'replace':
2025-07-02 06:41:17.940                     atags += '^' * la
2025-07-02 06:41:17.940                     btags += '^' * lb
2025-07-02 06:41:17.940                 elif tag == 'delete':
2025-07-02 06:41:17.940                     atags += '-' * la
2025-07-02 06:41:17.940                 elif tag == 'insert':
2025-07-02 06:41:17.940                     btags += '+' * lb
2025-07-02 06:41:17.940                 elif tag == 'equal':
2025-07-02 06:41:17.940                     atags += ' ' * la
2025-07-02 06:41:17.940                     btags += ' ' * lb
2025-07-02 06:41:17.940                 else:
2025-07-02 06:41:17.940                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.940             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.941         else:
2025-07-02 06:41:17.941             # the synch pair is identical
2025-07-02 06:41:17.941             yield '  ' + aelt
2025-07-02 06:41:17.941
2025-07-02 06:41:17.941         # pump out diffs from after the synch point
2025-07-02 06:41:17.941 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.941
2025-07-02 06:41:17.941 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.941 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.941
2025-07-02 06:41:17.941 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.941 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.941 alo = 316, ahi = 1101
2025-07-02 06:41:17.941 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.941 blo = 316, bhi = 1101
2025-07-02 06:41:17.941
2025-07-02 06:41:17.941     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.941         g = []
2025-07-02 06:41:17.941         if alo < ahi:
2025-07-02 06:41:17.942             if blo < bhi:
2025-07-02 06:41:17.942                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.942             else:
2025-07-02 06:41:17.942                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.942         elif blo < bhi:
2025-07-02 06:41:17.942             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.942
2025-07-02 06:41:17.942 >       yield from g
2025-07-02 06:41:17.942
2025-07-02 06:41:17.942 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.942 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.942
2025-07-02 06:41:17.942 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.942 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.942 alo = 316, ahi = 1101
2025-07-02 06:41:17.942 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.942 blo = 316, bhi = 1101
2025-07-02 06:41:17.942
2025-07-02 06:41:17.942     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.943         r"""
2025-07-02 06:41:17.943         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.943         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.943         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.943         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.943
2025-07-02 06:41:17.943         Example:
2025-07-02 06:41:17.943
2025-07-02 06:41:17.943         >>> d = Differ()
2025-07-02 06:41:17.943         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.943         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.943         >>> print(''.join(results), end="")
2025-07-02 06:41:17.943         - abcDefghiJkl
2025-07-02 06:41:17.943         + abcdefGhijkl
2025-07-02 06:41:17.943         """
2025-07-02 06:41:17.943
2025-07-02 06:41:17.943         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.944         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.944         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.944         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.944         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.944
2025-07-02 06:41:17.944         # search for the pair that matches best without being identical
2025-07-02 06:41:17.944         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.944         # on junk -- unless we have to)
2025-07-02 06:41:17.944         for j in range(blo, bhi):
2025-07-02 06:41:17.944             bj = b[j]
2025-07-02 06:41:17.944             cruncher.set_seq2(bj)
2025-07-02 06:41:17.944             for i in range(alo, ahi):
2025-07-02 06:41:17.944                 ai = a[i]
2025-07-02 06:41:17.944                 if ai == bj:
2025-07-02 06:41:17.944                     if eqi is None:
2025-07-02 06:41:17.944                         eqi, eqj = i, j
2025-07-02 06:41:17.944                     continue
2025-07-02 06:41:17.944                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.944                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.944                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.945                 # compares by a factor of 3.
2025-07-02 06:41:17.945                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.945                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.945                 # of the computation is cached by cruncher
2025-07-02 06:41:17.945                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.945                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.945                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.945                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.945         if best_ratio < cutoff:
2025-07-02 06:41:17.945             # no non-identical "pretty close" pair
2025-07-02 06:41:17.945             if eqi is None:
2025-07-02 06:41:17.945                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.945                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.945                 return
2025-07-02 06:41:17.945             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.945             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.945         else:
2025-07-02 06:41:17.945             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.945             eqi = None
2025-07-02 06:41:17.946
2025-07-02 06:41:17.946         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.946         # identical
2025-07-02 06:41:17.946
2025-07-02 06:41:17.946         # pump out diffs from before the synch point
2025-07-02 06:41:17.946         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.946
2025-07-02 06:41:17.946         # do intraline marking on the synch pair
2025-07-02 06:41:17.946         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.946         if eqi is None:
2025-07-02 06:41:17.946             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.946             atags = btags = ""
2025-07-02 06:41:17.946             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.946             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.946                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.946                 if tag == 'replace':
2025-07-02 06:41:17.946                     atags += '^' * la
2025-07-02 06:41:17.946                     btags += '^' * lb
2025-07-02 06:41:17.946                 elif tag == 'delete':
2025-07-02 06:41:17.946                     atags += '-' * la
2025-07-02 06:41:17.947                 elif tag == 'insert':
2025-07-02 06:41:17.947                     btags += '+' * lb
2025-07-02 06:41:17.947                 elif tag == 'equal':
2025-07-02 06:41:17.947                     atags += ' ' * la
2025-07-02 06:41:17.947                     btags += ' ' * lb
2025-07-02 06:41:17.947                 else:
2025-07-02 06:41:17.947                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.947             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.947         else:
2025-07-02 06:41:17.947             # the synch pair is identical
2025-07-02 06:41:17.947             yield '  ' + aelt
2025-07-02 06:41:17.947
2025-07-02 06:41:17.947         # pump out diffs from after the synch point
2025-07-02 06:41:17.947 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.947
2025-07-02 06:41:17.947 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.947 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.948
2025-07-02 06:41:17.948 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.948 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.948 alo = 317, ahi = 1101
2025-07-02 06:41:17.948 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.948 blo = 317, bhi = 1101
2025-07-02 06:41:17.948
2025-07-02 06:41:17.948     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.948         g = []
2025-07-02 06:41:17.948         if alo < ahi:
2025-07-02 06:41:17.948             if blo < bhi:
2025-07-02 06:41:17.948                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.948             else:
2025-07-02 06:41:17.948                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.948         elif blo < bhi:
2025-07-02 06:41:17.948             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.948
2025-07-02 06:41:17.948 >       yield from g
2025-07-02 06:41:17.949
2025-07-02 06:41:17.949 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.949 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.949
2025-07-02 06:41:17.949 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.949 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.949 alo = 317, ahi = 1101
2025-07-02 06:41:17.949 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.949 blo = 317, bhi = 1101
2025-07-02 06:41:17.949
2025-07-02 06:41:17.949     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.949         r"""
2025-07-02 06:41:17.949         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.949         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.949         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.949         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.949
2025-07-02 06:41:17.950         Example:
2025-07-02 06:41:17.950
2025-07-02 06:41:17.950         >>> d = Differ()
2025-07-02 06:41:17.950         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.950         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.950         >>> print(''.join(results), end="")
2025-07-02 06:41:17.950         - abcDefghiJkl
2025-07-02 06:41:17.950         + abcdefGhijkl
2025-07-02 06:41:17.950         """
2025-07-02 06:41:17.950
2025-07-02 06:41:17.950         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.950         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.950         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.950         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.950         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.950
2025-07-02 06:41:17.950         # search for the pair that matches best without being identical
2025-07-02 06:41:17.951         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.951         # on junk -- unless we have to)
2025-07-02 06:41:17.951         for j in range(blo, bhi):
2025-07-02 06:41:17.951             bj = b[j]
2025-07-02 06:41:17.951             cruncher.set_seq2(bj)
2025-07-02 06:41:17.951             for i in range(alo, ahi):
2025-07-02 06:41:17.951                 ai = a[i]
2025-07-02 06:41:17.951                 if ai == bj:
2025-07-02 06:41:17.951                     if eqi is None:
2025-07-02 06:41:17.951                         eqi, eqj = i, j
2025-07-02 06:41:17.951                     continue
2025-07-02 06:41:17.951                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.951                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.951                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.951                 # compares by a factor of 3.
2025-07-02 06:41:17.951                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.951                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.951                 # of the computation is cached by cruncher
2025-07-02 06:41:17.951                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.952                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.952                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.952                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.952         if best_ratio < cutoff:
2025-07-02 06:41:17.952             # no non-identical "pretty close" pair
2025-07-02 06:41:17.952             if eqi is None:
2025-07-02 06:41:17.952                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.952                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.952                 return
2025-07-02 06:41:17.952             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.952             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.952         else:
2025-07-02 06:41:17.952             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.952             eqi = None
2025-07-02 06:41:17.952
2025-07-02 06:41:17.952         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.952         # identical
2025-07-02 06:41:17.952
2025-07-02 06:41:17.952         # pump out diffs from before the synch point
2025-07-02 06:41:17.952         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.953
2025-07-02 06:41:17.953         # do intraline marking on the synch pair
2025-07-02 06:41:17.953         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.953         if eqi is None:
2025-07-02 06:41:17.953             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.953             atags = btags = ""
2025-07-02 06:41:17.953             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.953             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.953                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.953                 if tag == 'replace':
2025-07-02 06:41:17.953                     atags += '^' * la
2025-07-02 06:41:17.953                     btags += '^' * lb
2025-07-02 06:41:17.953                 elif tag == 'delete':
2025-07-02 06:41:17.953                     atags += '-' * la
2025-07-02 06:41:17.953                 elif tag == 'insert':
2025-07-02 06:41:17.953                     btags += '+' * lb
2025-07-02 06:41:17.953                 elif tag == 'equal':
2025-07-02 06:41:17.953                     atags += ' ' * la
2025-07-02 06:41:17.953                     btags += ' ' * lb
2025-07-02 06:41:17.954                 else:
2025-07-02 06:41:17.954                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.954             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.954         else:
2025-07-02 06:41:17.954             # the synch pair is identical
2025-07-02 06:41:17.954             yield '  ' + aelt
2025-07-02 06:41:17.954
2025-07-02 06:41:17.954         # pump out diffs from after the synch point
2025-07-02 06:41:17.954 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.954
2025-07-02 06:41:17.954 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.954 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.954
2025-07-02 06:41:17.954 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.954 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.954 alo = 318, ahi = 1101
2025-07-02 06:41:17.954 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.954 blo = 318, bhi = 1101
2025-07-02 06:41:17.954
2025-07-02 06:41:17.955     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.955         g = []
2025-07-02 06:41:17.955         if alo < ahi:
2025-07-02 06:41:17.955             if blo < bhi:
2025-07-02 06:41:17.955                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.955             else:
2025-07-02 06:41:17.955                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.955         elif blo < bhi:
2025-07-02 06:41:17.955             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.955
2025-07-02 06:41:17.955 >       yield from g
2025-07-02 06:41:17.955
2025-07-02 06:41:17.955 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.955 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.955
2025-07-02 06:41:17.955 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.955 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.955 alo = 318, ahi = 1101
2025-07-02 06:41:17.955 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.955 blo = 318, bhi = 1101
2025-07-02 06:41:17.956
2025-07-02 06:41:17.956     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.956         r"""
2025-07-02 06:41:17.956         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.956         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.956         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.956         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.956
2025-07-02 06:41:17.956         Example:
2025-07-02 06:41:17.956
2025-07-02 06:41:17.956         >>> d = Differ()
2025-07-02 06:41:17.956         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.956         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.956         >>> print(''.join(results), end="")
2025-07-02 06:41:17.956         - abcDefghiJkl
2025-07-02 06:41:17.956         + abcdefGhijkl
2025-07-02 06:41:17.956         """
2025-07-02 06:41:17.957
2025-07-02 06:41:17.957         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.957         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.957         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.957         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.957         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.957
2025-07-02 06:41:17.957         # search for the pair that matches best without being identical
2025-07-02 06:41:17.957         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.957         # on junk -- unless we have to)
2025-07-02 06:41:17.957         for j in range(blo, bhi):
2025-07-02 06:41:17.957             bj = b[j]
2025-07-02 06:41:17.957             cruncher.set_seq2(bj)
2025-07-02 06:41:17.957             for i in range(alo, ahi):
2025-07-02 06:41:17.957                 ai = a[i]
2025-07-02 06:41:17.957                 if ai == bj:
2025-07-02 06:41:17.957                     if eqi is None:
2025-07-02 06:41:17.957                         eqi, eqj = i, j
2025-07-02 06:41:17.957                     continue
2025-07-02 06:41:17.957                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.958                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.958                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.958                 # compares by a factor of 3.
2025-07-02 06:41:17.958                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.958                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.958                 # of the computation is cached by cruncher
2025-07-02 06:41:17.958                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.958                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.958                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.958                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.958         if best_ratio < cutoff:
2025-07-02 06:41:17.958             # no non-identical "pretty close" pair
2025-07-02 06:41:17.958             if eqi is None:
2025-07-02 06:41:17.958                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.958                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.958                 return
2025-07-02 06:41:17.958             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.958             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.959         else:
2025-07-02 06:41:17.959             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.959             eqi = None
2025-07-02 06:41:17.959
2025-07-02 06:41:17.959         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.959         # identical
2025-07-02 06:41:17.959
2025-07-02 06:41:17.959         # pump out diffs from before the synch point
2025-07-02 06:41:17.959         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.959
2025-07-02 06:41:17.959         # do intraline marking on the synch pair
2025-07-02 06:41:17.959         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.959         if eqi is None:
2025-07-02 06:41:17.959             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.959             atags = btags = ""
2025-07-02 06:41:17.959             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.959             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.959                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.959                 if tag == 'replace':
2025-07-02 06:41:17.960                     atags += '^' * la
2025-07-02 06:41:17.960                     btags += '^' * lb
2025-07-02 06:41:17.960                 elif tag == 'delete':
2025-07-02 06:41:17.960                     atags += '-' * la
2025-07-02 06:41:17.960                 elif tag == 'insert':
2025-07-02 06:41:17.960                     btags += '+' * lb
2025-07-02 06:41:17.960                 elif tag == 'equal':
2025-07-02 06:41:17.960                     atags += ' ' * la
2025-07-02 06:41:17.960                     btags += ' ' * lb
2025-07-02 06:41:17.960                 else:
2025-07-02 06:41:17.960                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.960             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.960         else:
2025-07-02 06:41:17.960             # the synch pair is identical
2025-07-02 06:41:17.960             yield '  ' + aelt
2025-07-02 06:41:17.960
2025-07-02 06:41:17.960         # pump out diffs from after the synch point
2025-07-02 06:41:17.960 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.960
2025-07-02 06:41:17.961 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.961 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.961
2025-07-02 06:41:17.961 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.961 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.961 alo = 319, ahi = 1101
2025-07-02 06:41:17.961 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.961 blo = 319, bhi = 1101
2025-07-02 06:41:17.961
2025-07-02 06:41:17.961     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.961         g = []
2025-07-02 06:41:17.961         if alo < ahi:
2025-07-02 06:41:17.961             if blo < bhi:
2025-07-02 06:41:17.961                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.961             else:
2025-07-02 06:41:17.961                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.961         elif blo < bhi:
2025-07-02 06:41:17.961             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.961
2025-07-02 06:41:17.961 >       yield from g
2025-07-02 06:41:17.962
2025-07-02 06:41:17.962 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.962 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.962
2025-07-02 06:41:17.962 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.962 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.962 alo = 319, ahi = 1101
2025-07-02 06:41:17.962 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.962 blo = 319, bhi = 1101
2025-07-02 06:41:17.962
2025-07-02 06:41:17.962     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.962         r"""
2025-07-02 06:41:17.962         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.962         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.962         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.962         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.962
2025-07-02 06:41:17.962         Example:
2025-07-02 06:41:17.962
2025-07-02 06:41:17.963         >>> d = Differ()
2025-07-02 06:41:17.963         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.963         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.963         >>> print(''.join(results), end="")
2025-07-02 06:41:17.963         - abcDefghiJkl
2025-07-02 06:41:17.963         + abcdefGhijkl
2025-07-02 06:41:17.963         """
2025-07-02 06:41:17.963
2025-07-02 06:41:17.963         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.963         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.963         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.963         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.963         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.963
2025-07-02 06:41:17.963         # search for the pair that matches best without being identical
2025-07-02 06:41:17.963         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.964         # on junk -- unless we have to)
2025-07-02 06:41:17.964         for j in range(blo, bhi):
2025-07-02 06:41:17.964             bj = b[j]
2025-07-02 06:41:17.964             cruncher.set_seq2(bj)
2025-07-02 06:41:17.964             for i in range(alo, ahi):
2025-07-02 06:41:17.964                 ai = a[i]
2025-07-02 06:41:17.964                 if ai == bj:
2025-07-02 06:41:17.964                     if eqi is None:
2025-07-02 06:41:17.964                         eqi, eqj = i, j
2025-07-02 06:41:17.964                     continue
2025-07-02 06:41:17.964                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.964                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.964                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.964                 # compares by a factor of 3.
2025-07-02 06:41:17.964                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.964                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.964                 # of the computation is cached by cruncher
2025-07-02 06:41:17.964                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.964                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.965                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.965                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.965         if best_ratio < cutoff:
2025-07-02 06:41:17.965             # no non-identical "pretty close" pair
2025-07-02 06:41:17.965             if eqi is None:
2025-07-02 06:41:17.965                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.965                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.965                 return
2025-07-02 06:41:17.965             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.965             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.965         else:
2025-07-02 06:41:17.965             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.965             eqi = None
2025-07-02 06:41:17.965
2025-07-02 06:41:17.965         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.965         # identical
2025-07-02 06:41:17.965
2025-07-02 06:41:17.965         # pump out diffs from before the synch point
2025-07-02 06:41:17.965         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.966
2025-07-02 06:41:17.966         # do intraline marking on the synch pair
2025-07-02 06:41:17.966         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.966         if eqi is None:
2025-07-02 06:41:17.966             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.966             atags = btags = ""
2025-07-02 06:41:17.966             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.966             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.966                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.966                 if tag == 'replace':
2025-07-02 06:41:17.966                     atags += '^' * la
2025-07-02 06:41:17.966                     btags += '^' * lb
2025-07-02 06:41:17.966                 elif tag == 'delete':
2025-07-02 06:41:17.966                     atags += '-' * la
2025-07-02 06:41:17.966                 elif tag == 'insert':
2025-07-02 06:41:17.966                     btags += '+' * lb
2025-07-02 06:41:17.966                 elif tag == 'equal':
2025-07-02 06:41:17.966                     atags += ' ' * la
2025-07-02 06:41:17.966                     btags += ' ' * lb
2025-07-02 06:41:17.967                 else:
2025-07-02 06:41:17.967                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.967             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.967         else:
2025-07-02 06:41:17.967             # the synch pair is identical
2025-07-02 06:41:17.967             yield '  ' + aelt
2025-07-02 06:41:17.967
2025-07-02 06:41:17.967         # pump out diffs from after the synch point
2025-07-02 06:41:17.967 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.967
2025-07-02 06:41:17.967 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.967 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.967
2025-07-02 06:41:17.967 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.967 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.967 alo = 320, ahi = 1101
2025-07-02 06:41:17.967 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.967 blo = 320, bhi = 1101
2025-07-02 06:41:17.968
2025-07-02 06:41:17.968     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.968         g = []
2025-07-02 06:41:17.968         if alo < ahi:
2025-07-02 06:41:17.968             if blo < bhi:
2025-07-02 06:41:17.968                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.968             else:
2025-07-02 06:41:17.968                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.968         elif blo < bhi:
2025-07-02 06:41:17.968             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.968
2025-07-02 06:41:17.968 >       yield from g
2025-07-02 06:41:17.968
2025-07-02 06:41:17.968 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.968 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.968
2025-07-02 06:41:17.968 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.968 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.968 alo = 320, ahi = 1101
2025-07-02 06:41:17.969 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.969 blo = 320, bhi = 1101
2025-07-02 06:41:17.969
2025-07-02 06:41:17.969     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.969         r"""
2025-07-02 06:41:17.969         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.969         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.969         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.969         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.969
2025-07-02 06:41:17.969         Example:
2025-07-02 06:41:17.969
2025-07-02 06:41:17.969         >>> d = Differ()
2025-07-02 06:41:17.969         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.969         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.969         >>> print(''.join(results), end="")
2025-07-02 06:41:17.969         - abcDefghiJkl
2025-07-02 06:41:17.969         + abcdefGhijkl
2025-07-02 06:41:17.970         """
2025-07-02 06:41:17.970
2025-07-02 06:41:17.970         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.970         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.970         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.970         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.970         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.970
2025-07-02 06:41:17.970         # search for the pair that matches best without being identical
2025-07-02 06:41:17.970         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.970         # on junk -- unless we have to)
2025-07-02 06:41:17.970         for j in range(blo, bhi):
2025-07-02 06:41:17.970             bj = b[j]
2025-07-02 06:41:17.970             cruncher.set_seq2(bj)
2025-07-02 06:41:17.970             for i in range(alo, ahi):
2025-07-02 06:41:17.970                 ai = a[i]
2025-07-02 06:41:17.970                 if ai == bj:
2025-07-02 06:41:17.970                     if eqi is None:
2025-07-02 06:41:17.971                         eqi, eqj = i, j
2025-07-02 06:41:17.971                     continue
2025-07-02 06:41:17.971                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.971                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.971                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.971                 # compares by a factor of 3.
2025-07-02 06:41:17.971                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.971                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.971                 # of the computation is cached by cruncher
2025-07-02 06:41:17.971                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.971                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.971                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.971                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.971         if best_ratio < cutoff:
2025-07-02 06:41:17.971             # no non-identical "pretty close" pair
2025-07-02 06:41:17.971             if eqi is None:
2025-07-02 06:41:17.971                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.971                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.971                 return
2025-07-02 06:41:17.971             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.972             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.972         else:
2025-07-02 06:41:17.972             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.972             eqi = None
2025-07-02 06:41:17.972
2025-07-02 06:41:17.972         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.972         # identical
2025-07-02 06:41:17.972
2025-07-02 06:41:17.972         # pump out diffs from before the synch point
2025-07-02 06:41:17.972         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.972
2025-07-02 06:41:17.972         # do intraline marking on the synch pair
2025-07-02 06:41:17.972         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.972         if eqi is None:
2025-07-02 06:41:17.972             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.972             atags = btags = ""
2025-07-02 06:41:17.972             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.972             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.972                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.973                 if tag == 'replace':
2025-07-02 06:41:17.973                     atags += '^' * la
2025-07-02 06:41:17.973                     btags += '^' * lb
2025-07-02 06:41:17.973                 elif tag == 'delete':
2025-07-02 06:41:17.973                     atags += '-' * la
2025-07-02 06:41:17.973                 elif tag == 'insert':
2025-07-02 06:41:17.973                     btags += '+' * lb
2025-07-02 06:41:17.973                 elif tag == 'equal':
2025-07-02 06:41:17.973                     atags += ' ' * la
2025-07-02 06:41:17.973                     btags += ' ' * lb
2025-07-02 06:41:17.973                 else:
2025-07-02 06:41:17.973                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.973             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.973         else:
2025-07-02 06:41:17.973             # the synch pair is identical
2025-07-02 06:41:17.973             yield '  ' + aelt
2025-07-02 06:41:17.973
2025-07-02 06:41:17.973         # pump out diffs from after the synch point
2025-07-02 06:41:17.973 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.973
2025-07-02 06:41:17.974 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.974 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.974
2025-07-02 06:41:17.974 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.974 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.974 alo = 321, ahi = 1101
2025-07-02 06:41:17.974 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.974 blo = 321, bhi = 1101
2025-07-02 06:41:17.974
2025-07-02 06:41:17.974     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.974         g = []
2025-07-02 06:41:17.974         if alo < ahi:
2025-07-02 06:41:17.974             if blo < bhi:
2025-07-02 06:41:17.974                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.974             else:
2025-07-02 06:41:17.974                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.974         elif blo < bhi:
2025-07-02 06:41:17.974             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.974
2025-07-02 06:41:17.975 >       yield from g
2025-07-02 06:41:17.975
2025-07-02 06:41:17.975 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.975 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.975
2025-07-02 06:41:17.975 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.975 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.975 alo = 321, ahi = 1101
2025-07-02 06:41:17.975 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.975 blo = 321, bhi = 1101
2025-07-02 06:41:17.975
2025-07-02 06:41:17.975     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.975         r"""
2025-07-02 06:41:17.975         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.975         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.975         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.975         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.975
2025-07-02 06:41:17.975         Example:
2025-07-02 06:41:17.976
2025-07-02 06:41:17.976         >>> d = Differ()
2025-07-02 06:41:17.976         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.976         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.976         >>> print(''.join(results), end="")
2025-07-02 06:41:17.976         - abcDefghiJkl
2025-07-02 06:41:17.976         + abcdefGhijkl
2025-07-02 06:41:17.976         """
2025-07-02 06:41:17.976
2025-07-02 06:41:17.976         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.976         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.976         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.976         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.976         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.976
2025-07-02 06:41:17.976         # search for the pair that matches best without being identical
2025-07-02 06:41:17.976         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.977         # on junk -- unless we have to)
2025-07-02 06:41:17.977         for j in range(blo, bhi):
2025-07-02 06:41:17.977             bj = b[j]
2025-07-02 06:41:17.977             cruncher.set_seq2(bj)
2025-07-02 06:41:17.977             for i in range(alo, ahi):
2025-07-02 06:41:17.977                 ai = a[i]
2025-07-02 06:41:17.977                 if ai == bj:
2025-07-02 06:41:17.977                     if eqi is None:
2025-07-02 06:41:17.977                         eqi, eqj = i, j
2025-07-02 06:41:17.977                     continue
2025-07-02 06:41:17.977                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.977                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.977                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.977                 # compares by a factor of 3.
2025-07-02 06:41:17.977                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.977                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.977                 # of the computation is cached by cruncher
2025-07-02 06:41:17.977                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.977                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.978                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.978                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.978         if best_ratio < cutoff:
2025-07-02 06:41:17.978             # no non-identical "pretty close" pair
2025-07-02 06:41:17.978             if eqi is None:
2025-07-02 06:41:17.978                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.978                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.978                 return
2025-07-02 06:41:17.978             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.978             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.978         else:
2025-07-02 06:41:17.978             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.978             eqi = None
2025-07-02 06:41:17.978
2025-07-02 06:41:17.978         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.978         # identical
2025-07-02 06:41:17.978
2025-07-02 06:41:17.978         # pump out diffs from before the synch point
2025-07-02 06:41:17.978         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.979
2025-07-02 06:41:17.979         # do intraline marking on the synch pair
2025-07-02 06:41:17.979         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.979         if eqi is None:
2025-07-02 06:41:17.979             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.979             atags = btags = ""
2025-07-02 06:41:17.979             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.979             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.979                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.979                 if tag == 'replace':
2025-07-02 06:41:17.979                     atags += '^' * la
2025-07-02 06:41:17.979                     btags += '^' * lb
2025-07-02 06:41:17.979                 elif tag == 'delete':
2025-07-02 06:41:17.979                     atags += '-' * la
2025-07-02 06:41:17.979                 elif tag == 'insert':
2025-07-02 06:41:17.979                     btags += '+' * lb
2025-07-02 06:41:17.979                 elif tag == 'equal':
2025-07-02 06:41:17.980                     atags += ' ' * la
2025-07-02 06:41:17.980                     btags += ' ' * lb
2025-07-02 06:41:17.980                 else:
2025-07-02 06:41:17.980                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.980             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.980         else:
2025-07-02 06:41:17.980             # the synch pair is identical
2025-07-02 06:41:17.980             yield '  ' + aelt
2025-07-02 06:41:17.980
2025-07-02 06:41:17.980         # pump out diffs from after the synch point
2025-07-02 06:41:17.980 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.980
2025-07-02 06:41:17.980 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.980 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.980
2025-07-02 06:41:17.980 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.980 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.980 alo = 322, ahi = 1101
2025-07-02 06:41:17.981 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.981 blo = 322, bhi = 1101
2025-07-02 06:41:17.981
2025-07-02 06:41:17.981     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.981         g = []
2025-07-02 06:41:17.981         if alo < ahi:
2025-07-02 06:41:17.981             if blo < bhi:
2025-07-02 06:41:17.981                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.981             else:
2025-07-02 06:41:17.981                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.981         elif blo < bhi:
2025-07-02 06:41:17.981             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.981
2025-07-02 06:41:17.981 >       yield from g
2025-07-02 06:41:17.981
2025-07-02 06:41:17.981 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.981 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.981
2025-07-02 06:41:17.982 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.982 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.982 alo = 322, ahi = 1101
2025-07-02 06:41:17.982 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.982 blo = 322, bhi = 1101
2025-07-02 06:41:17.982
2025-07-02 06:41:17.982     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.982         r"""
2025-07-02 06:41:17.982         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.982         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.982         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.982         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.982
2025-07-02 06:41:17.982         Example:
2025-07-02 06:41:17.982
2025-07-02 06:41:17.982         >>> d = Differ()
2025-07-02 06:41:17.982         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.982         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.982         >>> print(''.join(results), end="")
2025-07-02 06:41:17.983         - abcDefghiJkl
2025-07-02 06:41:17.983         + abcdefGhijkl
2025-07-02 06:41:17.983         """
2025-07-02 06:41:17.983
2025-07-02 06:41:17.983         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.983         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.983         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.983         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.983         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.983
2025-07-02 06:41:17.983         # search for the pair that matches best without being identical
2025-07-02 06:41:17.983         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.983         # on junk -- unless we have to)
2025-07-02 06:41:17.983         for j in range(blo, bhi):
2025-07-02 06:41:17.983             bj = b[j]
2025-07-02 06:41:17.983             cruncher.set_seq2(bj)
2025-07-02 06:41:17.983             for i in range(alo, ahi):
2025-07-02 06:41:17.984                 ai = a[i]
2025-07-02 06:41:17.984                 if ai == bj:
2025-07-02 06:41:17.984                     if eqi is None:
2025-07-02 06:41:17.984                         eqi, eqj = i, j
2025-07-02 06:41:17.984                     continue
2025-07-02 06:41:17.984                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.984                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.984                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.984                 # compares by a factor of 3.
2025-07-02 06:41:17.984                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.984                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.984                 # of the computation is cached by cruncher
2025-07-02 06:41:17.984                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.984                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.984                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.984                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.984         if best_ratio < cutoff:
2025-07-02 06:41:17.985             # no non-identical "pretty close" pair
2025-07-02 06:41:17.985             if eqi is None:
2025-07-02 06:41:17.985                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.985                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.985                 return
2025-07-02 06:41:17.985             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.985             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.985         else:
2025-07-02 06:41:17.985             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.985             eqi = None
2025-07-02 06:41:17.985
2025-07-02 06:41:17.985         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.985         # identical
2025-07-02 06:41:17.985
2025-07-02 06:41:17.985         # pump out diffs from before the synch point
2025-07-02 06:41:17.985         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.985
2025-07-02 06:41:17.985         # do intraline marking on the synch pair
2025-07-02 06:41:17.985         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.986         if eqi is None:
2025-07-02 06:41:17.986             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.986             atags = btags = ""
2025-07-02 06:41:17.986             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.986             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.986                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.986                 if tag == 'replace':
2025-07-02 06:41:17.986                     atags += '^' * la
2025-07-02 06:41:17.986                     btags += '^' * lb
2025-07-02 06:41:17.986                 elif tag == 'delete':
2025-07-02 06:41:17.986                     atags += '-' * la
2025-07-02 06:41:17.986                 elif tag == 'insert':
2025-07-02 06:41:17.986                     btags += '+' * lb
2025-07-02 06:41:17.986                 elif tag == 'equal':
2025-07-02 06:41:17.986                     atags += ' ' * la
2025-07-02 06:41:17.986                     btags += ' ' * lb
2025-07-02 06:41:17.986                 else:
2025-07-02 06:41:17.987                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.987             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.987         else:
2025-07-02 06:41:17.987             # the synch pair is identical
2025-07-02 06:41:17.987             yield '  ' + aelt
2025-07-02 06:41:17.987
2025-07-02 06:41:17.987         # pump out diffs from after the synch point
2025-07-02 06:41:17.987 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.987
2025-07-02 06:41:17.987 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.987 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.987
2025-07-02 06:41:17.987 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.987 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.987 alo = 323, ahi = 1101
2025-07-02 06:41:17.987 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.987 blo = 323, bhi = 1101
2025-07-02 06:41:17.987
2025-07-02 06:41:17.987     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.988         g = []
2025-07-02 06:41:17.988         if alo < ahi:
2025-07-02 06:41:17.988             if blo < bhi:
2025-07-02 06:41:17.988                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.988             else:
2025-07-02 06:41:17.988                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.988         elif blo < bhi:
2025-07-02 06:41:17.988             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.988
2025-07-02 06:41:17.988 >       yield from g
2025-07-02 06:41:17.988
2025-07-02 06:41:17.988 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.988 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.988
2025-07-02 06:41:17.988 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.988 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.988 alo = 323, ahi = 1101
2025-07-02 06:41:17.988 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.988 blo = 323, bhi = 1101
2025-07-02 06:41:17.989
2025-07-02 06:41:17.989     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.989         r"""
2025-07-02 06:41:17.989         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.989         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.989         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.989         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.989
2025-07-02 06:41:17.989         Example:
2025-07-02 06:41:17.989
2025-07-02 06:41:17.989         >>> d = Differ()
2025-07-02 06:41:17.989         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.989         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.989         >>> print(''.join(results), end="")
2025-07-02 06:41:17.989         - abcDefghiJkl
2025-07-02 06:41:17.989         + abcdefGhijkl
2025-07-02 06:41:17.989         """
2025-07-02 06:41:17.989
2025-07-02 06:41:17.989         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.990         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.990         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.990         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.990         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.990
2025-07-02 06:41:17.990         # search for the pair that matches best without being identical
2025-07-02 06:41:17.990         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.990         # on junk -- unless we have to)
2025-07-02 06:41:17.990         for j in range(blo, bhi):
2025-07-02 06:41:17.990             bj = b[j]
2025-07-02 06:41:17.990             cruncher.set_seq2(bj)
2025-07-02 06:41:17.990             for i in range(alo, ahi):
2025-07-02 06:41:17.990                 ai = a[i]
2025-07-02 06:41:17.990                 if ai == bj:
2025-07-02 06:41:17.990                     if eqi is None:
2025-07-02 06:41:17.990                         eqi, eqj = i, j
2025-07-02 06:41:17.990                     continue
2025-07-02 06:41:17.990                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.990                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.990                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.991                 # compares by a factor of 3.
2025-07-02 06:41:17.991                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.991                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.991                 # of the computation is cached by cruncher
2025-07-02 06:41:17.991                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.991                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.991                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.991                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.991         if best_ratio < cutoff:
2025-07-02 06:41:17.991             # no non-identical "pretty close" pair
2025-07-02 06:41:17.991             if eqi is None:
2025-07-02 06:41:17.991                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.991                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.991                 return
2025-07-02 06:41:17.991             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.991             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.991         else:
2025-07-02 06:41:17.991             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.991             eqi = None
2025-07-02 06:41:17.991
2025-07-02 06:41:17.992         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.992         # identical
2025-07-02 06:41:17.992
2025-07-02 06:41:17.992         # pump out diffs from before the synch point
2025-07-02 06:41:17.992         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.992
2025-07-02 06:41:17.992         # do intraline marking on the synch pair
2025-07-02 06:41:17.992         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.992         if eqi is None:
2025-07-02 06:41:17.992             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.992             atags = btags = ""
2025-07-02 06:41:17.992             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.992             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.992                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.992                 if tag == 'replace':
2025-07-02 06:41:17.992                     atags += '^' * la
2025-07-02 06:41:17.992                     btags += '^' * lb
2025-07-02 06:41:17.992                 elif tag == 'delete':
2025-07-02 06:41:17.992                     atags += '-' * la
2025-07-02 06:41:17.992                 elif tag == 'insert':
2025-07-02 06:41:17.993                     btags += '+' * lb
2025-07-02 06:41:17.993                 elif tag == 'equal':
2025-07-02 06:41:17.993                     atags += ' ' * la
2025-07-02 06:41:17.993                     btags += ' ' * lb
2025-07-02 06:41:17.993                 else:
2025-07-02 06:41:17.993                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.993             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.993         else:
2025-07-02 06:41:17.993             # the synch pair is identical
2025-07-02 06:41:17.993             yield '  ' + aelt
2025-07-02 06:41:17.993
2025-07-02 06:41:17.993         # pump out diffs from after the synch point
2025-07-02 06:41:17.993 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:17.993
2025-07-02 06:41:17.993 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:17.993 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.993
2025-07-02 06:41:17.993 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.993 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.993 alo = 324, ahi = 1101
2025-07-02 06:41:17.993 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.994 blo = 324, bhi = 1101
2025-07-02 06:41:17.994
2025-07-02 06:41:17.994     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.994         g = []
2025-07-02 06:41:17.994         if alo < ahi:
2025-07-02 06:41:17.994             if blo < bhi:
2025-07-02 06:41:17.994                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.994             else:
2025-07-02 06:41:17.994                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:17.994         elif blo < bhi:
2025-07-02 06:41:17.994             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:17.994
2025-07-02 06:41:17.994 >       yield from g
2025-07-02 06:41:17.994
2025-07-02 06:41:17.994 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:17.994 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:17.994
2025-07-02 06:41:17.994 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:17.994 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:17.995 alo = 324, ahi = 1101
2025-07-02 06:41:17.995 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:17.995 blo = 324, bhi = 1101
2025-07-02 06:41:17.995
2025-07-02 06:41:17.995     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:17.995         r"""
2025-07-02 06:41:17.995         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:17.995         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:17.995         synch point, and intraline difference marking is done on the
2025-07-02 06:41:17.995         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:17.995
2025-07-02 06:41:17.995         Example:
2025-07-02 06:41:17.995
2025-07-02 06:41:17.995         >>> d = Differ()
2025-07-02 06:41:17.995         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:17.995         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:17.995         >>> print(''.join(results), end="")
2025-07-02 06:41:17.996         - abcDefghiJkl
2025-07-02 06:41:17.996         + abcdefGhijkl
2025-07-02 06:41:17.996         """
2025-07-02 06:41:17.996
2025-07-02 06:41:17.996         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:17.996         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:17.996         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:17.996         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:17.996         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:17.996
2025-07-02 06:41:17.996         # search for the pair that matches best without being identical
2025-07-02 06:41:17.996         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:17.996         # on junk -- unless we have to)
2025-07-02 06:41:17.996         for j in range(blo, bhi):
2025-07-02 06:41:17.996             bj = b[j]
2025-07-02 06:41:17.996             cruncher.set_seq2(bj)
2025-07-02 06:41:17.996             for i in range(alo, ahi):
2025-07-02 06:41:17.997                 ai = a[i]
2025-07-02 06:41:17.997                 if ai == bj:
2025-07-02 06:41:17.997                     if eqi is None:
2025-07-02 06:41:17.997                         eqi, eqj = i, j
2025-07-02 06:41:17.997                     continue
2025-07-02 06:41:17.997                 cruncher.set_seq1(ai)
2025-07-02 06:41:17.997                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:17.997                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:17.997                 # compares by a factor of 3.
2025-07-02 06:41:17.997                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:17.997                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:17.997                 # of the computation is cached by cruncher
2025-07-02 06:41:17.997                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:17.997                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:17.997                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:17.997                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:17.997         if best_ratio < cutoff:
2025-07-02 06:41:17.997             # no non-identical "pretty close" pair
2025-07-02 06:41:17.997             if eqi is None:
2025-07-02 06:41:17.997                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:17.998                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:17.998                 return
2025-07-02 06:41:17.998             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:17.998             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:17.998         else:
2025-07-02 06:41:17.998             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:17.998             eqi = None
2025-07-02 06:41:17.998
2025-07-02 06:41:17.998         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:17.998         # identical
2025-07-02 06:41:17.998
2025-07-02 06:41:17.998         # pump out diffs from before the synch point
2025-07-02 06:41:17.998         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:17.998
2025-07-02 06:41:17.998         # do intraline marking on the synch pair
2025-07-02 06:41:17.998         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:17.998         if eqi is None:
2025-07-02 06:41:17.998             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:17.998             atags = btags = ""
2025-07-02 06:41:17.998             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:17.999             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:17.999                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:17.999                 if tag == 'replace':
2025-07-02 06:41:17.999                     atags += '^' * la
2025-07-02 06:41:17.999                     btags += '^' * lb
2025-07-02 06:41:17.999                 elif tag == 'delete':
2025-07-02 06:41:17.999                     atags += '-' * la
2025-07-02 06:41:17.999                 elif tag == 'insert':
2025-07-02 06:41:17.999                     btags += '+' * lb
2025-07-02 06:41:17.999                 elif tag == 'equal':
2025-07-02 06:41:17.999                     atags += ' ' * la
2025-07-02 06:41:17.999                     btags += ' ' * lb
2025-07-02 06:41:17.999                 else:
2025-07-02 06:41:17.999                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:17.999             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:17.999         else:
2025-07-02 06:41:17.999             # the synch pair is identical
2025-07-02 06:41:17.999             yield '  ' + aelt
2025-07-02 06:41:17.999
2025-07-02 06:41:17.999         # pump out diffs from after the synch point
2025-07-02 06:41:17.999 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.000
2025-07-02 06:41:18.000 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.000 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.000
2025-07-02 06:41:18.000 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.000 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.000 alo = 325, ahi = 1101
2025-07-02 06:41:18.000 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.000 blo = 325, bhi = 1101
2025-07-02 06:41:18.000
2025-07-02 06:41:18.000     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.000         g = []
2025-07-02 06:41:18.000         if alo < ahi:
2025-07-02 06:41:18.000             if blo < bhi:
2025-07-02 06:41:18.000                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.000             else:
2025-07-02 06:41:18.000                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.000         elif blo < bhi:
2025-07-02 06:41:18.000             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001 >       yield from g
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.001 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.001 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.001 alo = 325, ahi = 1101
2025-07-02 06:41:18.001 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.001 blo = 325, bhi = 1101
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.001         r"""
2025-07-02 06:41:18.001         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.001         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.001         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.001         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.001
2025-07-02 06:41:18.001         Example:
2025-07-02 06:41:18.002
2025-07-02 06:41:18.002         >>> d = Differ()
2025-07-02 06:41:18.002         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.002         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.002         >>> print(''.join(results), end="")
2025-07-02 06:41:18.002         - abcDefghiJkl
2025-07-02 06:41:18.002         + abcdefGhijkl
2025-07-02 06:41:18.002         """
2025-07-02 06:41:18.002
2025-07-02 06:41:18.002         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.002         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.002         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.002         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.002         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.002
2025-07-02 06:41:18.002         # search for the pair that matches best without being identical
2025-07-02 06:41:18.002         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.002         # on junk -- unless we have to)
2025-07-02 06:41:18.003         for j in range(blo, bhi):
2025-07-02 06:41:18.003             bj = b[j]
2025-07-02 06:41:18.003             cruncher.set_seq2(bj)
2025-07-02 06:41:18.003             for i in range(alo, ahi):
2025-07-02 06:41:18.003                 ai = a[i]
2025-07-02 06:41:18.003                 if ai == bj:
2025-07-02 06:41:18.003                     if eqi is None:
2025-07-02 06:41:18.003                         eqi, eqj = i, j
2025-07-02 06:41:18.003                     continue
2025-07-02 06:41:18.003                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.003                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.003                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.003                 # compares by a factor of 3.
2025-07-02 06:41:18.003                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.003                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.003                 # of the computation is cached by cruncher
2025-07-02 06:41:18.003                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.003                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.003                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.003                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.004         if best_ratio < cutoff:
2025-07-02 06:41:18.004             # no non-identical "pretty close" pair
2025-07-02 06:41:18.004             if eqi is None:
2025-07-02 06:41:18.004                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.004                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.004                 return
2025-07-02 06:41:18.004             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.004             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.004         else:
2025-07-02 06:41:18.004             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.004             eqi = None
2025-07-02 06:41:18.004
2025-07-02 06:41:18.004         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.004         # identical
2025-07-02 06:41:18.004
2025-07-02 06:41:18.004         # pump out diffs from before the synch point
2025-07-02 06:41:18.004         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.004
2025-07-02 06:41:18.004         # do intraline marking on the synch pair
2025-07-02 06:41:18.005         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.005         if eqi is None:
2025-07-02 06:41:18.005             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.005             atags = btags = ""
2025-07-02 06:41:18.005             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.005             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.005                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.005                 if tag == 'replace':
2025-07-02 06:41:18.005                     atags += '^' * la
2025-07-02 06:41:18.005                     btags += '^' * lb
2025-07-02 06:41:18.005                 elif tag == 'delete':
2025-07-02 06:41:18.005                     atags += '-' * la
2025-07-02 06:41:18.005                 elif tag == 'insert':
2025-07-02 06:41:18.005                     btags += '+' * lb
2025-07-02 06:41:18.005                 elif tag == 'equal':
2025-07-02 06:41:18.005                     atags += ' ' * la
2025-07-02 06:41:18.005                     btags += ' ' * lb
2025-07-02 06:41:18.005                 else:
2025-07-02 06:41:18.005                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.005             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.006         else:
2025-07-02 06:41:18.006             # the synch pair is identical
2025-07-02 06:41:18.006             yield '  ' + aelt
2025-07-02 06:41:18.006
2025-07-02 06:41:18.006         # pump out diffs from after the synch point
2025-07-02 06:41:18.006 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.006
2025-07-02 06:41:18.006 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.006 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.006
2025-07-02 06:41:18.006 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.006 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.006 alo = 326, ahi = 1101
2025-07-02 06:41:18.006 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.006 blo = 326, bhi = 1101
2025-07-02 06:41:18.006
2025-07-02 06:41:18.006     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.006         g = []
2025-07-02 06:41:18.006         if alo < ahi:
2025-07-02 06:41:18.006             if blo < bhi:
2025-07-02 06:41:18.007                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.007             else:
2025-07-02 06:41:18.007                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.007         elif blo < bhi:
2025-07-02 06:41:18.007             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.007
2025-07-02 06:41:18.007 >       yield from g
2025-07-02 06:41:18.007
2025-07-02 06:41:18.007 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.007 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.007
2025-07-02 06:41:18.007 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.007 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.007 alo = 326, ahi = 1101
2025-07-02 06:41:18.007 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.007 blo = 326, bhi = 1101
2025-07-02 06:41:18.007
2025-07-02 06:41:18.007     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.007         r"""
2025-07-02 06:41:18.007         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.008         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.008         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.008         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.008
2025-07-02 06:41:18.008         Example:
2025-07-02 06:41:18.008
2025-07-02 06:41:18.008         >>> d = Differ()
2025-07-02 06:41:18.008         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.008         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.008         >>> print(''.join(results), end="")
2025-07-02 06:41:18.008         - abcDefghiJkl
2025-07-02 06:41:18.008         + abcdefGhijkl
2025-07-02 06:41:18.008         """
2025-07-02 06:41:18.008
2025-07-02 06:41:18.008         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.008         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.008         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.008         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.009         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.009
2025-07-02 06:41:18.009         # search for the pair that matches best without being identical
2025-07-02 06:41:18.009         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.009         # on junk -- unless we have to)
2025-07-02 06:41:18.009         for j in range(blo, bhi):
2025-07-02 06:41:18.009             bj = b[j]
2025-07-02 06:41:18.009             cruncher.set_seq2(bj)
2025-07-02 06:41:18.009             for i in range(alo, ahi):
2025-07-02 06:41:18.009                 ai = a[i]
2025-07-02 06:41:18.009                 if ai == bj:
2025-07-02 06:41:18.009                     if eqi is None:
2025-07-02 06:41:18.009                         eqi, eqj = i, j
2025-07-02 06:41:18.009                     continue
2025-07-02 06:41:18.009                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.009                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.009                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.009                 # compares by a factor of 3.
2025-07-02 06:41:18.009                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.009                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.010                 # of the computation is cached by cruncher
2025-07-02 06:41:18.010                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.010                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.010                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.010                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.010         if best_ratio < cutoff:
2025-07-02 06:41:18.010             # no non-identical "pretty close" pair
2025-07-02 06:41:18.010             if eqi is None:
2025-07-02 06:41:18.010                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.010                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.010                 return
2025-07-02 06:41:18.010             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.010             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.010         else:
2025-07-02 06:41:18.010             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.010             eqi = None
2025-07-02 06:41:18.010
2025-07-02 06:41:18.010         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.010         # identical
2025-07-02 06:41:18.010
2025-07-02 06:41:18.011         # pump out diffs from before the synch point
2025-07-02 06:41:18.011         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.011
2025-07-02 06:41:18.011         # do intraline marking on the synch pair
2025-07-02 06:41:18.011         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.011         if eqi is None:
2025-07-02 06:41:18.011             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.011             atags = btags = ""
2025-07-02 06:41:18.011             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.011             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.011                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.011                 if tag == 'replace':
2025-07-02 06:41:18.011                     atags += '^' * la
2025-07-02 06:41:18.011                     btags += '^' * lb
2025-07-02 06:41:18.011                 elif tag == 'delete':
2025-07-02 06:41:18.011                     atags += '-' * la
2025-07-02 06:41:18.011                 elif tag == 'insert':
2025-07-02 06:41:18.011                     btags += '+' * lb
2025-07-02 06:41:18.012                 elif tag == 'equal':
2025-07-02 06:41:18.012                     atags += ' ' * la
2025-07-02 06:41:18.012                     btags += ' ' * lb
2025-07-02 06:41:18.012                 else:
2025-07-02 06:41:18.012                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.012             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.012         else:
2025-07-02 06:41:18.012             # the synch pair is identical
2025-07-02 06:41:18.012             yield '  ' + aelt
2025-07-02 06:41:18.012
2025-07-02 06:41:18.012         # pump out diffs from after the synch point
2025-07-02 06:41:18.012 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.012
2025-07-02 06:41:18.012 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.012 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.012
2025-07-02 06:41:18.012 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.013 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.013 alo = 327, ahi = 1101
2025-07-02 06:41:18.013 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.013 blo = 327, bhi = 1101
2025-07-02 06:41:18.013
2025-07-02 06:41:18.013     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.013         g = []
2025-07-02 06:41:18.013         if alo < ahi:
2025-07-02 06:41:18.013             if blo < bhi:
2025-07-02 06:41:18.013                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.013             else:
2025-07-02 06:41:18.013                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.013         elif blo < bhi:
2025-07-02 06:41:18.013             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.013
2025-07-02 06:41:18.013 >       yield from g
2025-07-02 06:41:18.013
2025-07-02 06:41:18.013 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.013 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.014
2025-07-02 06:41:18.014 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.014 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.014 alo = 327, ahi = 1101
2025-07-02 06:41:18.014 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.014 blo = 327, bhi = 1101
2025-07-02 06:41:18.014
2025-07-02 06:41:18.014     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.014         r"""
2025-07-02 06:41:18.014         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.014         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.014         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.014         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.014
2025-07-02 06:41:18.014         Example:
2025-07-02 06:41:18.014
2025-07-02 06:41:18.014         >>> d = Differ()
2025-07-02 06:41:18.014         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.015         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.015         >>> print(''.join(results), end="")
2025-07-02 06:41:18.015         - abcDefghiJkl
2025-07-02 06:41:18.015         + abcdefGhijkl
2025-07-02 06:41:18.015         """
2025-07-02 06:41:18.015
2025-07-02 06:41:18.015         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.015         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.015         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.015         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.015         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.015
2025-07-02 06:41:18.015         # search for the pair that matches best without being identical
2025-07-02 06:41:18.015         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.015         # on junk -- unless we have to)
2025-07-02 06:41:18.015         for j in range(blo, bhi):
2025-07-02 06:41:18.015             bj = b[j]
2025-07-02 06:41:18.016             cruncher.set_seq2(bj)
2025-07-02 06:41:18.016             for i in range(alo, ahi):
2025-07-02 06:41:18.016                 ai = a[i]
2025-07-02 06:41:18.016                 if ai == bj:
2025-07-02 06:41:18.016                     if eqi is None:
2025-07-02 06:41:18.016                         eqi, eqj = i, j
2025-07-02 06:41:18.016                     continue
2025-07-02 06:41:18.016                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.016                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.016                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.016                 # compares by a factor of 3.
2025-07-02 06:41:18.016                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.016                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.016                 # of the computation is cached by cruncher
2025-07-02 06:41:18.016                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.016                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.016                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.016                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.016         if best_ratio < cutoff:
2025-07-02 06:41:18.017             # no non-identical "pretty close" pair
2025-07-02 06:41:18.017             if eqi is None:
2025-07-02 06:41:18.017                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.017                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.017                 return
2025-07-02 06:41:18.017             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.017             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.017         else:
2025-07-02 06:41:18.017             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.017             eqi = None
2025-07-02 06:41:18.017
2025-07-02 06:41:18.017         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.017         # identical
2025-07-02 06:41:18.017
2025-07-02 06:41:18.017         # pump out diffs from before the synch point
2025-07-02 06:41:18.017         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.017
2025-07-02 06:41:18.017         # do intraline marking on the synch pair
2025-07-02 06:41:18.017         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.018         if eqi is None:
2025-07-02 06:41:18.018             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.018             atags = btags = ""
2025-07-02 06:41:18.018             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.018             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.018                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.018                 if tag == 'replace':
2025-07-02 06:41:18.018                     atags += '^' * la
2025-07-02 06:41:18.018                     btags += '^' * lb
2025-07-02 06:41:18.018                 elif tag == 'delete':
2025-07-02 06:41:18.018                     atags += '-' * la
2025-07-02 06:41:18.018                 elif tag == 'insert':
2025-07-02 06:41:18.018                     btags += '+' * lb
2025-07-02 06:41:18.018                 elif tag == 'equal':
2025-07-02 06:41:18.018                     atags += ' ' * la
2025-07-02 06:41:18.018                     btags += ' ' * lb
2025-07-02 06:41:18.018                 else:
2025-07-02 06:41:18.018                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.018             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.018         else:
2025-07-02 06:41:18.019             # the synch pair is identical
2025-07-02 06:41:18.019             yield '  ' + aelt
2025-07-02 06:41:18.019
2025-07-02 06:41:18.019         # pump out diffs from after the synch point
2025-07-02 06:41:18.019 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.019
2025-07-02 06:41:18.019 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.019 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.019
2025-07-02 06:41:18.019 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.019 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.019 alo = 328, ahi = 1101
2025-07-02 06:41:18.019 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.019 blo = 328, bhi = 1101
2025-07-02 06:41:18.019
2025-07-02 06:41:18.019     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.019         g = []
2025-07-02 06:41:18.019         if alo < ahi:
2025-07-02 06:41:18.019             if blo < bhi:
2025-07-02 06:41:18.019                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.020             else:
2025-07-02 06:41:18.020                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.020         elif blo < bhi:
2025-07-02 06:41:18.020             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.020
2025-07-02 06:41:18.020 >       yield from g
2025-07-02 06:41:18.020
2025-07-02 06:41:18.020 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.020 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.020
2025-07-02 06:41:18.020 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.020 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.020 alo = 328, ahi = 1101
2025-07-02 06:41:18.020 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.020 blo = 328, bhi = 1101
2025-07-02 06:41:18.020
2025-07-02 06:41:18.020     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.020         r"""
2025-07-02 06:41:18.020         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.021         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.021         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.021         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.021
2025-07-02 06:41:18.021         Example:
2025-07-02 06:41:18.021
2025-07-02 06:41:18.021         >>> d = Differ()
2025-07-02 06:41:18.021         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.021         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.021         >>> print(''.join(results), end="")
2025-07-02 06:41:18.021         - abcDefghiJkl
2025-07-02 06:41:18.021         + abcdefGhijkl
2025-07-02 06:41:18.021         """
2025-07-02 06:41:18.021
2025-07-02 06:41:18.021         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.021         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.022         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.022         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.022         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.022
2025-07-02 06:41:18.022         # search for the pair that matches best without being identical
2025-07-02 06:41:18.022         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.022         # on junk -- unless we have to)
2025-07-02 06:41:18.022         for j in range(blo, bhi):
2025-07-02 06:41:18.022             bj = b[j]
2025-07-02 06:41:18.022             cruncher.set_seq2(bj)
2025-07-02 06:41:18.022             for i in range(alo, ahi):
2025-07-02 06:41:18.022                 ai = a[i]
2025-07-02 06:41:18.022                 if ai == bj:
2025-07-02 06:41:18.022                     if eqi is None:
2025-07-02 06:41:18.022                         eqi, eqj = i, j
2025-07-02 06:41:18.022                     continue
2025-07-02 06:41:18.022                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.022                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.022                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.023                 # compares by a factor of 3.
2025-07-02 06:41:18.023                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.023                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.023                 # of the computation is cached by cruncher
2025-07-02 06:41:18.023                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.023                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.023                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.023                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.023         if best_ratio < cutoff:
2025-07-02 06:41:18.023             # no non-identical "pretty close" pair
2025-07-02 06:41:18.023             if eqi is None:
2025-07-02 06:41:18.023                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.023                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.023                 return
2025-07-02 06:41:18.023             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.023             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.023         else:
2025-07-02 06:41:18.023             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.023             eqi = None
2025-07-02 06:41:18.024
2025-07-02 06:41:18.024         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.024         # identical
2025-07-02 06:41:18.024
2025-07-02 06:41:18.024         # pump out diffs from before the synch point
2025-07-02 06:41:18.024         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.024
2025-07-02 06:41:18.024         # do intraline marking on the synch pair
2025-07-02 06:41:18.024         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.024         if eqi is None:
2025-07-02 06:41:18.024             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.024             atags = btags = ""
2025-07-02 06:41:18.024             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.024             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.024                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.024                 if tag == 'replace':
2025-07-02 06:41:18.024                     atags += '^' * la
2025-07-02 06:41:18.024                     btags += '^' * lb
2025-07-02 06:41:18.024                 elif tag == 'delete':
2025-07-02 06:41:18.024                     atags += '-' * la
2025-07-02 06:41:18.025                 elif tag == 'insert':
2025-07-02 06:41:18.025                     btags += '+' * lb
2025-07-02 06:41:18.025                 elif tag == 'equal':
2025-07-02 06:41:18.025                     atags += ' ' * la
2025-07-02 06:41:18.025                     btags += ' ' * lb
2025-07-02 06:41:18.025                 else:
2025-07-02 06:41:18.025                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.025             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.025         else:
2025-07-02 06:41:18.025             # the synch pair is identical
2025-07-02 06:41:18.025             yield '  ' + aelt
2025-07-02 06:41:18.025
2025-07-02 06:41:18.025         # pump out diffs from after the synch point
2025-07-02 06:41:18.025 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.025
2025-07-02 06:41:18.025 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.025 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.025
2025-07-02 06:41:18.025 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.025 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.026 alo = 329, ahi = 1101
2025-07-02 06:41:18.026 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.026 blo = 329, bhi = 1101
2025-07-02 06:41:18.026
2025-07-02 06:41:18.026     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.026         g = []
2025-07-02 06:41:18.026         if alo < ahi:
2025-07-02 06:41:18.026             if blo < bhi:
2025-07-02 06:41:18.026                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.026             else:
2025-07-02 06:41:18.026                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.026         elif blo < bhi:
2025-07-02 06:41:18.026             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.026
2025-07-02 06:41:18.026 >       yield from g
2025-07-02 06:41:18.026
2025-07-02 06:41:18.026 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.026 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.027
2025-07-02 06:41:18.027 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.027 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.027 alo = 329, ahi = 1101
2025-07-02 06:41:18.027 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.027 blo = 329, bhi = 1101
2025-07-02 06:41:18.027
2025-07-02 06:41:18.027     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.027         r"""
2025-07-02 06:41:18.027         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.027         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.027         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.027         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.027
2025-07-02 06:41:18.027         Example:
2025-07-02 06:41:18.027
2025-07-02 06:41:18.027         >>> d = Differ()
2025-07-02 06:41:18.027         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.027         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.027         >>> print(''.join(results), end="")
2025-07-02 06:41:18.028         - abcDefghiJkl
2025-07-02 06:41:18.028         + abcdefGhijkl
2025-07-02 06:41:18.028         """
2025-07-02 06:41:18.028
2025-07-02 06:41:18.028         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.028         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.028         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.028         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.028         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.028
2025-07-02 06:41:18.028         # search for the pair that matches best without being identical
2025-07-02 06:41:18.028         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.028         # on junk -- unless we have to)
2025-07-02 06:41:18.028         for j in range(blo, bhi):
2025-07-02 06:41:18.028             bj = b[j]
2025-07-02 06:41:18.028             cruncher.set_seq2(bj)
2025-07-02 06:41:18.028             for i in range(alo, ahi):
2025-07-02 06:41:18.028                 ai = a[i]
2025-07-02 06:41:18.029                 if ai == bj:
2025-07-02 06:41:18.029                     if eqi is None:
2025-07-02 06:41:18.029                         eqi, eqj = i, j
2025-07-02 06:41:18.029                     continue
2025-07-02 06:41:18.029                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.029                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.029                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.029                 # compares by a factor of 3.
2025-07-02 06:41:18.029                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.029                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.029                 # of the computation is cached by cruncher
2025-07-02 06:41:18.029                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.029                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.029                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.029                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.029         if best_ratio < cutoff:
2025-07-02 06:41:18.029             # no non-identical "pretty close" pair
2025-07-02 06:41:18.029             if eqi is None:
2025-07-02 06:41:18.029                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.030                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.030                 return
2025-07-02 06:41:18.030             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.030             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.030         else:
2025-07-02 06:41:18.030             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.030             eqi = None
2025-07-02 06:41:18.030
2025-07-02 06:41:18.030         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.030         # identical
2025-07-02 06:41:18.030
2025-07-02 06:41:18.030         # pump out diffs from before the synch point
2025-07-02 06:41:18.030         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.030
2025-07-02 06:41:18.030         # do intraline marking on the synch pair
2025-07-02 06:41:18.030         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.030         if eqi is None:
2025-07-02 06:41:18.030             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.030             atags = btags = ""
2025-07-02 06:41:18.031             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.031             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.031                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.031                 if tag == 'replace':
2025-07-02 06:41:18.031                     atags += '^' * la
2025-07-02 06:41:18.031                     btags += '^' * lb
2025-07-02 06:41:18.031                 elif tag == 'delete':
2025-07-02 06:41:18.031                     atags += '-' * la
2025-07-02 06:41:18.031                 elif tag == 'insert':
2025-07-02 06:41:18.031                     btags += '+' * lb
2025-07-02 06:41:18.031                 elif tag == 'equal':
2025-07-02 06:41:18.031                     atags += ' ' * la
2025-07-02 06:41:18.031                     btags += ' ' * lb
2025-07-02 06:41:18.031                 else:
2025-07-02 06:41:18.031                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.031             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.031         else:
2025-07-02 06:41:18.031             # the synch pair is identical
2025-07-02 06:41:18.031             yield '  ' + aelt
2025-07-02 06:41:18.031
2025-07-02 06:41:18.032         # pump out diffs from after the synch point
2025-07-02 06:41:18.032 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.032
2025-07-02 06:41:18.032 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.032 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.032
2025-07-02 06:41:18.032 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.032 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.032 alo = 330, ahi = 1101
2025-07-02 06:41:18.032 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.032 blo = 330, bhi = 1101
2025-07-02 06:41:18.032
2025-07-02 06:41:18.032     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.032         g = []
2025-07-02 06:41:18.032         if alo < ahi:
2025-07-02 06:41:18.032             if blo < bhi:
2025-07-02 06:41:18.032                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.032             else:
2025-07-02 06:41:18.032                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.032         elif blo < bhi:
2025-07-02 06:41:18.033             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.033
2025-07-02 06:41:18.033 >       yield from g
2025-07-02 06:41:18.033
2025-07-02 06:41:18.033 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.033 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.033
2025-07-02 06:41:18.033 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.033 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.033 alo = 330, ahi = 1101
2025-07-02 06:41:18.033 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.033 blo = 330, bhi = 1101
2025-07-02 06:41:18.033
2025-07-02 06:41:18.033     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.033         r"""
2025-07-02 06:41:18.033         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.033         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.033         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.033         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.033
2025-07-02 06:41:18.034         Example:
2025-07-02 06:41:18.034
2025-07-02 06:41:18.034         >>> d = Differ()
2025-07-02 06:41:18.034         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.034         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.034         >>> print(''.join(results), end="")
2025-07-02 06:41:18.034         - abcDefghiJkl
2025-07-02 06:41:18.034         + abcdefGhijkl
2025-07-02 06:41:18.034         """
2025-07-02 06:41:18.034
2025-07-02 06:41:18.034         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.034         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.034         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.034         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.034         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.034
2025-07-02 06:41:18.034         # search for the pair that matches best without being identical
2025-07-02 06:41:18.034         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.034         # on junk -- unless we have to)
2025-07-02 06:41:18.035         for j in range(blo, bhi):
2025-07-02 06:41:18.035             bj = b[j]
2025-07-02 06:41:18.035             cruncher.set_seq2(bj)
2025-07-02 06:41:18.035             for i in range(alo, ahi):
2025-07-02 06:41:18.035                 ai = a[i]
2025-07-02 06:41:18.035                 if ai == bj:
2025-07-02 06:41:18.035                     if eqi is None:
2025-07-02 06:41:18.035                         eqi, eqj = i, j
2025-07-02 06:41:18.035                     continue
2025-07-02 06:41:18.035                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.035                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.035                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.035                 # compares by a factor of 3.
2025-07-02 06:41:18.035                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.035                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.035                 # of the computation is cached by cruncher
2025-07-02 06:41:18.035                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.036                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.036                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.036                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.036         if best_ratio < cutoff:
2025-07-02 06:41:18.036             # no non-identical "pretty close" pair
2025-07-02 06:41:18.036             if eqi is None:
2025-07-02 06:41:18.036                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.036                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.036                 return
2025-07-02 06:41:18.036             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.036             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.036         else:
2025-07-02 06:41:18.036             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.036             eqi = None
2025-07-02 06:41:18.036
2025-07-02 06:41:18.036         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.036         # identical
2025-07-02 06:41:18.036
2025-07-02 06:41:18.036         # pump out diffs from before the synch point
2025-07-02 06:41:18.036         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.037
2025-07-02 06:41:18.037         # do intraline marking on the synch pair
2025-07-02 06:41:18.037         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.037         if eqi is None:
2025-07-02 06:41:18.037             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.037             atags = btags = ""
2025-07-02 06:41:18.037             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.037             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.037                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.037                 if tag == 'replace':
2025-07-02 06:41:18.037                     atags += '^' * la
2025-07-02 06:41:18.037                     btags += '^' * lb
2025-07-02 06:41:18.037                 elif tag == 'delete':
2025-07-02 06:41:18.037                     atags += '-' * la
2025-07-02 06:41:18.037                 elif tag == 'insert':
2025-07-02 06:41:18.037                     btags += '+' * lb
2025-07-02 06:41:18.037                 elif tag == 'equal':
2025-07-02 06:41:18.037                     atags += ' ' * la
2025-07-02 06:41:18.037                     btags += ' ' * lb
2025-07-02 06:41:18.037                 else:
2025-07-02 06:41:18.038                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.038             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.038         else:
2025-07-02 06:41:18.038             # the synch pair is identical
2025-07-02 06:41:18.038             yield '  ' + aelt
2025-07-02 06:41:18.038
2025-07-02 06:41:18.038         # pump out diffs from after the synch point
2025-07-02 06:41:18.038 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.038
2025-07-02 06:41:18.038 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.038 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.038
2025-07-02 06:41:18.038 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.038 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.038 alo = 331, ahi = 1101
2025-07-02 06:41:18.038 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.038 blo = 331, bhi = 1101
2025-07-02 06:41:18.038
2025-07-02 06:41:18.038     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.038         g = []
2025-07-02 06:41:18.039         if alo < ahi:
2025-07-02 06:41:18.039             if blo < bhi:
2025-07-02 06:41:18.039                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.039             else:
2025-07-02 06:41:18.039                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.039         elif blo < bhi:
2025-07-02 06:41:18.039             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.039
2025-07-02 06:41:18.039 >       yield from g
2025-07-02 06:41:18.039
2025-07-02 06:41:18.039 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.039 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.039
2025-07-02 06:41:18.039 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.039 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.039 alo = 331, ahi = 1101
2025-07-02 06:41:18.039 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.039 blo = 331, bhi = 1101
2025-07-02 06:41:18.039
2025-07-02 06:41:18.040     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.040         r"""
2025-07-02 06:41:18.040         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.040         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.040         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.040         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.040
2025-07-02 06:41:18.040         Example:
2025-07-02 06:41:18.040
2025-07-02 06:41:18.040         >>> d = Differ()
2025-07-02 06:41:18.040         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.040         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.040         >>> print(''.join(results), end="")
2025-07-02 06:41:18.040         - abcDefghiJkl
2025-07-02 06:41:18.040         + abcdefGhijkl
2025-07-02 06:41:18.040         """
2025-07-02 06:41:18.040
2025-07-02 06:41:18.040         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.041         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.041         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.041         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.041         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.041
2025-07-02 06:41:18.041         # search for the pair that matches best without being identical
2025-07-02 06:41:18.041         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.041         # on junk -- unless we have to)
2025-07-02 06:41:18.041         for j in range(blo, bhi):
2025-07-02 06:41:18.041             bj = b[j]
2025-07-02 06:41:18.041             cruncher.set_seq2(bj)
2025-07-02 06:41:18.041             for i in range(alo, ahi):
2025-07-02 06:41:18.041                 ai = a[i]
2025-07-02 06:41:18.041                 if ai == bj:
2025-07-02 06:41:18.041                     if eqi is None:
2025-07-02 06:41:18.041                         eqi, eqj = i, j
2025-07-02 06:41:18.041                     continue
2025-07-02 06:41:18.041                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.042                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.042                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.042                 # compares by a factor of 3.
2025-07-02 06:41:18.042                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.042                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.042                 # of the computation is cached by cruncher
2025-07-02 06:41:18.042                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.042                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.042                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.042                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.042         if best_ratio < cutoff:
2025-07-02 06:41:18.042             # no non-identical "pretty close" pair
2025-07-02 06:41:18.042             if eqi is None:
2025-07-02 06:41:18.042                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.042                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.042                 return
2025-07-02 06:41:18.042             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.042             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.042         else:
2025-07-02 06:41:18.042             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.043             eqi = None
2025-07-02 06:41:18.043
2025-07-02 06:41:18.043         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.043         # identical
2025-07-02 06:41:18.043
2025-07-02 06:41:18.043         # pump out diffs from before the synch point
2025-07-02 06:41:18.043         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.043
2025-07-02 06:41:18.043         # do intraline marking on the synch pair
2025-07-02 06:41:18.043         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.043         if eqi is None:
2025-07-02 06:41:18.043             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.043             atags = btags = ""
2025-07-02 06:41:18.043             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.043             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.043                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.043                 if tag == 'replace':
2025-07-02 06:41:18.043                     atags += '^' * la
2025-07-02 06:41:18.043                     btags += '^' * lb
2025-07-02 06:41:18.044                 elif tag == 'delete':
2025-07-02 06:41:18.044                     atags += '-' * la
2025-07-02 06:41:18.044                 elif tag == 'insert':
2025-07-02 06:41:18.044                     btags += '+' * lb
2025-07-02 06:41:18.044                 elif tag == 'equal':
2025-07-02 06:41:18.044                     atags += ' ' * la
2025-07-02 06:41:18.044                     btags += ' ' * lb
2025-07-02 06:41:18.044                 else:
2025-07-02 06:41:18.044                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.044             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.044         else:
2025-07-02 06:41:18.044             # the synch pair is identical
2025-07-02 06:41:18.044             yield '  ' + aelt
2025-07-02 06:41:18.044
2025-07-02 06:41:18.044         # pump out diffs from after the synch point
2025-07-02 06:41:18.044 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.044
2025-07-02 06:41:18.044 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.044 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.044
2025-07-02 06:41:18.045 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.045 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.045 alo = 334, ahi = 1101
2025-07-02 06:41:18.045 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.045 blo = 334, bhi = 1101
2025-07-02 06:41:18.045
2025-07-02 06:41:18.045     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.045         g = []
2025-07-02 06:41:18.045         if alo < ahi:
2025-07-02 06:41:18.045             if blo < bhi:
2025-07-02 06:41:18.045                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.045             else:
2025-07-02 06:41:18.045                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.045         elif blo < bhi:
2025-07-02 06:41:18.045             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.045
2025-07-02 06:41:18.045 >       yield from g
2025-07-02 06:41:18.045
2025-07-02 06:41:18.045 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.045 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.046
2025-07-02 06:41:18.046 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.046 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.046 alo = 334, ahi = 1101
2025-07-02 06:41:18.046 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.046 blo = 334, bhi = 1101
2025-07-02 06:41:18.046
2025-07-02 06:41:18.046     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.046         r"""
2025-07-02 06:41:18.046         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.046         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.046         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.046         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.046
2025-07-02 06:41:18.046         Example:
2025-07-02 06:41:18.046
2025-07-02 06:41:18.046         >>> d = Differ()
2025-07-02 06:41:18.046         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.046         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.046         >>> print(''.join(results), end="")
2025-07-02 06:41:18.047         - abcDefghiJkl
2025-07-02 06:41:18.047         + abcdefGhijkl
2025-07-02 06:41:18.047         """
2025-07-02 06:41:18.047
2025-07-02 06:41:18.047         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.047         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.047         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.047         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.047         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.047
2025-07-02 06:41:18.047         # search for the pair that matches best without being identical
2025-07-02 06:41:18.047         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.047         # on junk -- unless we have to)
2025-07-02 06:41:18.047         for j in range(blo, bhi):
2025-07-02 06:41:18.047             bj = b[j]
2025-07-02 06:41:18.047             cruncher.set_seq2(bj)
2025-07-02 06:41:18.047             for i in range(alo, ahi):
2025-07-02 06:41:18.047                 ai = a[i]
2025-07-02 06:41:18.048                 if ai == bj:
2025-07-02 06:41:18.048                     if eqi is None:
2025-07-02 06:41:18.048                         eqi, eqj = i, j
2025-07-02 06:41:18.048                     continue
2025-07-02 06:41:18.048                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.048                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.048                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.048                 # compares by a factor of 3.
2025-07-02 06:41:18.048                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.048                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.048                 # of the computation is cached by cruncher
2025-07-02 06:41:18.048                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.048                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.048                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.048                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.048         if best_ratio < cutoff:
2025-07-02 06:41:18.048             # no non-identical "pretty close" pair
2025-07-02 06:41:18.048             if eqi is None:
2025-07-02 06:41:18.048                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.049                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.049                 return
2025-07-02 06:41:18.049             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.049             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.049         else:
2025-07-02 06:41:18.049             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.049             eqi = None
2025-07-02 06:41:18.049
2025-07-02 06:41:18.049         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.049         # identical
2025-07-02 06:41:18.049
2025-07-02 06:41:18.049         # pump out diffs from before the synch point
2025-07-02 06:41:18.049         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.049
2025-07-02 06:41:18.049         # do intraline marking on the synch pair
2025-07-02 06:41:18.049         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.049         if eqi is None:
2025-07-02 06:41:18.049             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.049             atags = btags = ""
2025-07-02 06:41:18.049             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.050             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.050                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.050                 if tag == 'replace':
2025-07-02 06:41:18.050                     atags += '^' * la
2025-07-02 06:41:18.050                     btags += '^' * lb
2025-07-02 06:41:18.050                 elif tag == 'delete':
2025-07-02 06:41:18.050                     atags += '-' * la
2025-07-02 06:41:18.050                 elif tag == 'insert':
2025-07-02 06:41:18.050                     btags += '+' * lb
2025-07-02 06:41:18.050                 elif tag == 'equal':
2025-07-02 06:41:18.050                     atags += ' ' * la
2025-07-02 06:41:18.050                     btags += ' ' * lb
2025-07-02 06:41:18.050                 else:
2025-07-02 06:41:18.050                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.050             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.050         else:
2025-07-02 06:41:18.050             # the synch pair is identical
2025-07-02 06:41:18.050             yield '  ' + aelt
2025-07-02 06:41:18.050
2025-07-02 06:41:18.050         # pump out diffs from after the synch point
2025-07-02 06:41:18.051 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.051
2025-07-02 06:41:18.051 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.051 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.051
2025-07-02 06:41:18.051 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.051 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.051 alo = 335, ahi = 1101
2025-07-02 06:41:18.051 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.051 blo = 335, bhi = 1101
2025-07-02 06:41:18.051
2025-07-02 06:41:18.051     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.051         g = []
2025-07-02 06:41:18.051         if alo < ahi:
2025-07-02 06:41:18.051             if blo < bhi:
2025-07-02 06:41:18.051                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.051             else:
2025-07-02 06:41:18.051                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.051         elif blo < bhi:
2025-07-02 06:41:18.051             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.051
2025-07-02 06:41:18.052 >       yield from g
2025-07-02 06:41:18.052
2025-07-02 06:41:18.052 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.052 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.052
2025-07-02 06:41:18.052 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.052 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.052 alo = 335, ahi = 1101
2025-07-02 06:41:18.052 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.052 blo = 335, bhi = 1101
2025-07-02 06:41:18.052
2025-07-02 06:41:18.052     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.052         r"""
2025-07-02 06:41:18.052         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.052         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.052         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.052         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.052
2025-07-02 06:41:18.052         Example:
2025-07-02 06:41:18.052
2025-07-02 06:41:18.053         >>> d = Differ()
2025-07-02 06:41:18.053         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.053         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.053         >>> print(''.join(results), end="")
2025-07-02 06:41:18.053         - abcDefghiJkl
2025-07-02 06:41:18.053         + abcdefGhijkl
2025-07-02 06:41:18.053         """
2025-07-02 06:41:18.053
2025-07-02 06:41:18.053         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.053         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.053         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.053         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.053         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.053
2025-07-02 06:41:18.053         # search for the pair that matches best without being identical
2025-07-02 06:41:18.053         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.054         # on junk -- unless we have to)
2025-07-02 06:41:18.054         for j in range(blo, bhi):
2025-07-02 06:41:18.054             bj = b[j]
2025-07-02 06:41:18.054             cruncher.set_seq2(bj)
2025-07-02 06:41:18.054             for i in range(alo, ahi):
2025-07-02 06:41:18.054                 ai = a[i]
2025-07-02 06:41:18.054                 if ai == bj:
2025-07-02 06:41:18.054                     if eqi is None:
2025-07-02 06:41:18.054                         eqi, eqj = i, j
2025-07-02 06:41:18.054                     continue
2025-07-02 06:41:18.054                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.054                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.054                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.054                 # compares by a factor of 3.
2025-07-02 06:41:18.054                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.054                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.054                 # of the computation is cached by cruncher
2025-07-02 06:41:18.054                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.054                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.055                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.055                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.055         if best_ratio < cutoff:
2025-07-02 06:41:18.055             # no non-identical "pretty close" pair
2025-07-02 06:41:18.055             if eqi is None:
2025-07-02 06:41:18.055                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.055                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.055                 return
2025-07-02 06:41:18.055             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.055             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.055         else:
2025-07-02 06:41:18.055             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.055             eqi = None
2025-07-02 06:41:18.055
2025-07-02 06:41:18.055         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.055         # identical
2025-07-02 06:41:18.055
2025-07-02 06:41:18.055         # pump out diffs from before the synch point
2025-07-02 06:41:18.055         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.055
2025-07-02 06:41:18.055         # do intraline marking on the synch pair
2025-07-02 06:41:18.056         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.056         if eqi is None:
2025-07-02 06:41:18.056             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.056             atags = btags = ""
2025-07-02 06:41:18.056             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.056             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.056                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.056                 if tag == 'replace':
2025-07-02 06:41:18.056                     atags += '^' * la
2025-07-02 06:41:18.056                     btags += '^' * lb
2025-07-02 06:41:18.056                 elif tag == 'delete':
2025-07-02 06:41:18.056                     atags += '-' * la
2025-07-02 06:41:18.056                 elif tag == 'insert':
2025-07-02 06:41:18.056                     btags += '+' * lb
2025-07-02 06:41:18.056                 elif tag == 'equal':
2025-07-02 06:41:18.056                     atags += ' ' * la
2025-07-02 06:41:18.056                     btags += ' ' * lb
2025-07-02 06:41:18.056                 else:
2025-07-02 06:41:18.056                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.057             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.057         else:
2025-07-02 06:41:18.057             # the synch pair is identical
2025-07-02 06:41:18.057             yield '  ' + aelt
2025-07-02 06:41:18.057
2025-07-02 06:41:18.057         # pump out diffs from after the synch point
2025-07-02 06:41:18.057 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.057
2025-07-02 06:41:18.057 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.057 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.057
2025-07-02 06:41:18.057 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.057 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.057 alo = 336, ahi = 1101
2025-07-02 06:41:18.057 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.057 blo = 336, bhi = 1101
2025-07-02 06:41:18.058
2025-07-02 06:41:18.058     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.058         g = []
2025-07-02 06:41:18.058         if alo < ahi:
2025-07-02 06:41:18.058             if blo < bhi:
2025-07-02 06:41:18.058                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.058             else:
2025-07-02 06:41:18.058                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.058         elif blo < bhi:
2025-07-02 06:41:18.058             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.058
2025-07-02 06:41:18.058 >       yield from g
2025-07-02 06:41:18.058
2025-07-02 06:41:18.058 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.058 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.058
2025-07-02 06:41:18.058 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.058 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.058 alo = 336, ahi = 1101
2025-07-02 06:41:18.058 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.059 blo = 336, bhi = 1101
2025-07-02 06:41:18.059
2025-07-02 06:41:18.059     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.059         r"""
2025-07-02 06:41:18.059         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.059         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.059         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.059         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.059
2025-07-02 06:41:18.059         Example:
2025-07-02 06:41:18.059
2025-07-02 06:41:18.059         >>> d = Differ()
2025-07-02 06:41:18.059         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.059         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.059         >>> print(''.join(results), end="")
2025-07-02 06:41:18.059         - abcDefghiJkl
2025-07-02 06:41:18.059         + abcdefGhijkl
2025-07-02 06:41:18.060         """
2025-07-02 06:41:18.060
2025-07-02 06:41:18.060         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.060         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.060         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.060         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.060         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.060
2025-07-02 06:41:18.060         # search for the pair that matches best without being identical
2025-07-02 06:41:18.060         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.060         # on junk -- unless we have to)
2025-07-02 06:41:18.060         for j in range(blo, bhi):
2025-07-02 06:41:18.060             bj = b[j]
2025-07-02 06:41:18.060             cruncher.set_seq2(bj)
2025-07-02 06:41:18.060             for i in range(alo, ahi):
2025-07-02 06:41:18.060                 ai = a[i]
2025-07-02 06:41:18.060                 if ai == bj:
2025-07-02 06:41:18.060                     if eqi is None:
2025-07-02 06:41:18.060                         eqi, eqj = i, j
2025-07-02 06:41:18.060                     continue
2025-07-02 06:41:18.061                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.061                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.061                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.061                 # compares by a factor of 3.
2025-07-02 06:41:18.061                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.061                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.061                 # of the computation is cached by cruncher
2025-07-02 06:41:18.061                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.061                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.061                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.061                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.061         if best_ratio < cutoff:
2025-07-02 06:41:18.061             # no non-identical "pretty close" pair
2025-07-02 06:41:18.061             if eqi is None:
2025-07-02 06:41:18.061                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.061                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.061                 return
2025-07-02 06:41:18.061             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.061             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.062         else:
2025-07-02 06:41:18.062             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.062             eqi = None
2025-07-02 06:41:18.062
2025-07-02 06:41:18.062         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.062         # identical
2025-07-02 06:41:18.062
2025-07-02 06:41:18.062         # pump out diffs from before the synch point
2025-07-02 06:41:18.062         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.062
2025-07-02 06:41:18.062         # do intraline marking on the synch pair
2025-07-02 06:41:18.062         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.062         if eqi is None:
2025-07-02 06:41:18.062             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.062             atags = btags = ""
2025-07-02 06:41:18.062             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.062             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.062                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.062                 if tag == 'replace':
2025-07-02 06:41:18.063                     atags += '^' * la
2025-07-02 06:41:18.063                     btags += '^' * lb
2025-07-02 06:41:18.063                 elif tag == 'delete':
2025-07-02 06:41:18.063                     atags += '-' * la
2025-07-02 06:41:18.063                 elif tag == 'insert':
2025-07-02 06:41:18.063                     btags += '+' * lb
2025-07-02 06:41:18.063                 elif tag == 'equal':
2025-07-02 06:41:18.063                     atags += ' ' * la
2025-07-02 06:41:18.063                     btags += ' ' * lb
2025-07-02 06:41:18.063                 else:
2025-07-02 06:41:18.063                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.063             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.063         else:
2025-07-02 06:41:18.063             # the synch pair is identical
2025-07-02 06:41:18.063             yield '  ' + aelt
2025-07-02 06:41:18.063
2025-07-02 06:41:18.063         # pump out diffs from after the synch point
2025-07-02 06:41:18.063 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.063
2025-07-02 06:41:18.063 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.064 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.064
2025-07-02 06:41:18.064 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.064 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.064 alo = 337, ahi = 1101
2025-07-02 06:41:18.064 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.064 blo = 337, bhi = 1101
2025-07-02 06:41:18.064
2025-07-02 06:41:18.064     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.064         g = []
2025-07-02 06:41:18.064         if alo < ahi:
2025-07-02 06:41:18.064             if blo < bhi:
2025-07-02 06:41:18.064                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.064             else:
2025-07-02 06:41:18.064                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.064         elif blo < bhi:
2025-07-02 06:41:18.064             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.064
2025-07-02 06:41:18.064 >       yield from g
2025-07-02 06:41:18.064
2025-07-02 06:41:18.065 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.065 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.065
2025-07-02 06:41:18.065 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.065 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.065 alo = 337, ahi = 1101
2025-07-02 06:41:18.065 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.065 blo = 337, bhi = 1101
2025-07-02 06:41:18.065
2025-07-02 06:41:18.065     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.065         r"""
2025-07-02 06:41:18.065         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.065         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.065         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.065         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.065
2025-07-02 06:41:18.065         Example:
2025-07-02 06:41:18.065
2025-07-02 06:41:18.066         >>> d = Differ()
2025-07-02 06:41:18.066         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.066         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.066         >>> print(''.join(results), end="")
2025-07-02 06:41:18.066         - abcDefghiJkl
2025-07-02 06:41:18.066         + abcdefGhijkl
2025-07-02 06:41:18.066         """
2025-07-02 06:41:18.066
2025-07-02 06:41:18.066         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.066         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.066         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.066         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.066         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.066
2025-07-02 06:41:18.066         # search for the pair that matches best without being identical
2025-07-02 06:41:18.066         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.066         # on junk -- unless we have to)
2025-07-02 06:41:18.067         for j in range(blo, bhi):
2025-07-02 06:41:18.067             bj = b[j]
2025-07-02 06:41:18.067             cruncher.set_seq2(bj)
2025-07-02 06:41:18.067             for i in range(alo, ahi):
2025-07-02 06:41:18.067                 ai = a[i]
2025-07-02 06:41:18.067                 if ai == bj:
2025-07-02 06:41:18.067                     if eqi is None:
2025-07-02 06:41:18.067                         eqi, eqj = i, j
2025-07-02 06:41:18.067                     continue
2025-07-02 06:41:18.067                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.067                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.067                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.067                 # compares by a factor of 3.
2025-07-02 06:41:18.067                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.067                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.067                 # of the computation is cached by cruncher
2025-07-02 06:41:18.067                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.067                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.067                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.067                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.068         if best_ratio < cutoff:
2025-07-02 06:41:18.068             # no non-identical "pretty close" pair
2025-07-02 06:41:18.068             if eqi is None:
2025-07-02 06:41:18.068                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.068                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.068                 return
2025-07-02 06:41:18.068             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.068             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.068         else:
2025-07-02 06:41:18.068             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.068             eqi = None
2025-07-02 06:41:18.068
2025-07-02 06:41:18.068         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.068         # identical
2025-07-02 06:41:18.068
2025-07-02 06:41:18.068         # pump out diffs from before the synch point
2025-07-02 06:41:18.068         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.068
2025-07-02 06:41:18.068         # do intraline marking on the synch pair
2025-07-02 06:41:18.068         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.068         if eqi is None:
2025-07-02 06:41:18.069             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.069             atags = btags = ""
2025-07-02 06:41:18.069             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.069             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.069                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.069                 if tag == 'replace':
2025-07-02 06:41:18.069                     atags += '^' * la
2025-07-02 06:41:18.069                     btags += '^' * lb
2025-07-02 06:41:18.069                 elif tag == 'delete':
2025-07-02 06:41:18.069                     atags += '-' * la
2025-07-02 06:41:18.069                 elif tag == 'insert':
2025-07-02 06:41:18.069                     btags += '+' * lb
2025-07-02 06:41:18.069                 elif tag == 'equal':
2025-07-02 06:41:18.069                     atags += ' ' * la
2025-07-02 06:41:18.069                     btags += ' ' * lb
2025-07-02 06:41:18.069                 else:
2025-07-02 06:41:18.069                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.069             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.069         else:
2025-07-02 06:41:18.069             # the synch pair is identical
2025-07-02 06:41:18.070             yield '  ' + aelt
2025-07-02 06:41:18.070
2025-07-02 06:41:18.070         # pump out diffs from after the synch point
2025-07-02 06:41:18.070 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.070
2025-07-02 06:41:18.070 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.070 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.070
2025-07-02 06:41:18.070 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.070 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.070 alo = 338, ahi = 1101
2025-07-02 06:41:18.070 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.070 blo = 338, bhi = 1101
2025-07-02 06:41:18.070
2025-07-02 06:41:18.070     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.070         g = []
2025-07-02 06:41:18.070         if alo < ahi:
2025-07-02 06:41:18.070             if blo < bhi:
2025-07-02 06:41:18.070                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.070             else:
2025-07-02 06:41:18.071                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.071         elif blo < bhi:
2025-07-02 06:41:18.071             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.071
2025-07-02 06:41:18.071 >       yield from g
2025-07-02 06:41:18.071
2025-07-02 06:41:18.071 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.071 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.071
2025-07-02 06:41:18.071 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.071 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.071 alo = 338, ahi = 1101
2025-07-02 06:41:18.071 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.071 blo = 338, bhi = 1101
2025-07-02 06:41:18.071
2025-07-02 06:41:18.071     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.071         r"""
2025-07-02 06:41:18.071         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.071         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.071         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.071         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.072
2025-07-02 06:41:18.072         Example:
2025-07-02 06:41:18.072
2025-07-02 06:41:18.072         >>> d = Differ()
2025-07-02 06:41:18.072         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.072         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.072         >>> print(''.join(results), end="")
2025-07-02 06:41:18.072         - abcDefghiJkl
2025-07-02 06:41:18.072         + abcdefGhijkl
2025-07-02 06:41:18.072         """
2025-07-02 06:41:18.072
2025-07-02 06:41:18.072         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.072         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.072         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.072         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.072         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.072
2025-07-02 06:41:18.072         # search for the pair that matches best without being identical
2025-07-02 06:41:18.073         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.073         # on junk -- unless we have to)
2025-07-02 06:41:18.073         for j in range(blo, bhi):
2025-07-02 06:41:18.073             bj = b[j]
2025-07-02 06:41:18.073             cruncher.set_seq2(bj)
2025-07-02 06:41:18.073             for i in range(alo, ahi):
2025-07-02 06:41:18.073                 ai = a[i]
2025-07-02 06:41:18.073                 if ai == bj:
2025-07-02 06:41:18.073                     if eqi is None:
2025-07-02 06:41:18.073                         eqi, eqj = i, j
2025-07-02 06:41:18.073                     continue
2025-07-02 06:41:18.073                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.073                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.073                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.073                 # compares by a factor of 3.
2025-07-02 06:41:18.073                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.073                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.073                 # of the computation is cached by cruncher
2025-07-02 06:41:18.074                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.074                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.074                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.074                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.074         if best_ratio < cutoff:
2025-07-02 06:41:18.074             # no non-identical "pretty close" pair
2025-07-02 06:41:18.074             if eqi is None:
2025-07-02 06:41:18.074                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.074                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.074                 return
2025-07-02 06:41:18.074             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.074             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.074         else:
2025-07-02 06:41:18.074             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.074             eqi = None
2025-07-02 06:41:18.074
2025-07-02 06:41:18.074         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.074         # identical
2025-07-02 06:41:18.075
2025-07-02 06:41:18.075         # pump out diffs from before the synch point
2025-07-02 06:41:18.075         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.075
2025-07-02 06:41:18.075         # do intraline marking on the synch pair
2025-07-02 06:41:18.075         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.075         if eqi is None:
2025-07-02 06:41:18.075             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.075             atags = btags = ""
2025-07-02 06:41:18.075             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.075             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.075                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.075                 if tag == 'replace':
2025-07-02 06:41:18.075                     atags += '^' * la
2025-07-02 06:41:18.075                     btags += '^' * lb
2025-07-02 06:41:18.075                 elif tag == 'delete':
2025-07-02 06:41:18.075                     atags += '-' * la
2025-07-02 06:41:18.075                 elif tag == 'insert':
2025-07-02 06:41:18.075                     btags += '+' * lb
2025-07-02 06:41:18.076                 elif tag == 'equal':
2025-07-02 06:41:18.076                     atags += ' ' * la
2025-07-02 06:41:18.076                     btags += ' ' * lb
2025-07-02 06:41:18.076                 else:
2025-07-02 06:41:18.076                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.076             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.076         else:
2025-07-02 06:41:18.076             # the synch pair is identical
2025-07-02 06:41:18.076             yield '  ' + aelt
2025-07-02 06:41:18.076
2025-07-02 06:41:18.076         # pump out diffs from after the synch point
2025-07-02 06:41:18.076 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.076
2025-07-02 06:41:18.076 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.076 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.076
2025-07-02 06:41:18.076 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.076 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.076 alo = 339, ahi = 1101
2025-07-02 06:41:18.076 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.077 blo = 339, bhi = 1101
2025-07-02 06:41:18.077
2025-07-02 06:41:18.077     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.077         g = []
2025-07-02 06:41:18.077         if alo < ahi:
2025-07-02 06:41:18.077             if blo < bhi:
2025-07-02 06:41:18.077                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.077             else:
2025-07-02 06:41:18.077                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.077         elif blo < bhi:
2025-07-02 06:41:18.077             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.077
2025-07-02 06:41:18.077 >       yield from g
2025-07-02 06:41:18.077
2025-07-02 06:41:18.077 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.077 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.077
2025-07-02 06:41:18.077 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.077 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.077 alo = 339, ahi = 1101
2025-07-02 06:41:18.078 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.078 blo = 339, bhi = 1101
2025-07-02 06:41:18.078
2025-07-02 06:41:18.078     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.078         r"""
2025-07-02 06:41:18.078         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.078         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.078         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.078         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.078
2025-07-02 06:41:18.078         Example:
2025-07-02 06:41:18.078
2025-07-02 06:41:18.078         >>> d = Differ()
2025-07-02 06:41:18.078         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.078         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.078         >>> print(''.join(results), end="")
2025-07-02 06:41:18.078         - abcDefghiJkl
2025-07-02 06:41:18.078         + abcdefGhijkl
2025-07-02 06:41:18.078         """
2025-07-02 06:41:18.079
2025-07-02 06:41:18.079         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.079         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.079         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.079         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.079         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.079
2025-07-02 06:41:18.079         # search for the pair that matches best without being identical
2025-07-02 06:41:18.079         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.079         # on junk -- unless we have to)
2025-07-02 06:41:18.079         for j in range(blo, bhi):
2025-07-02 06:41:18.079             bj = b[j]
2025-07-02 06:41:18.079             cruncher.set_seq2(bj)
2025-07-02 06:41:18.079             for i in range(alo, ahi):
2025-07-02 06:41:18.079                 ai = a[i]
2025-07-02 06:41:18.079                 if ai == bj:
2025-07-02 06:41:18.079                     if eqi is None:
2025-07-02 06:41:18.079                         eqi, eqj = i, j
2025-07-02 06:41:18.079                     continue
2025-07-02 06:41:18.079                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.080                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.080                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.080                 # compares by a factor of 3.
2025-07-02 06:41:18.080                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.080                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.080                 # of the computation is cached by cruncher
2025-07-02 06:41:18.080                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.080                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.080                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.080                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.080         if best_ratio < cutoff:
2025-07-02 06:41:18.080             # no non-identical "pretty close" pair
2025-07-02 06:41:18.080             if eqi is None:
2025-07-02 06:41:18.080                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.080                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.080                 return
2025-07-02 06:41:18.080             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.080             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.080         else:
2025-07-02 06:41:18.080             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.081             eqi = None
2025-07-02 06:41:18.081
2025-07-02 06:41:18.081         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.081         # identical
2025-07-02 06:41:18.081
2025-07-02 06:41:18.081         # pump out diffs from before the synch point
2025-07-02 06:41:18.081         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.081
2025-07-02 06:41:18.081         # do intraline marking on the synch pair
2025-07-02 06:41:18.081         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.081         if eqi is None:
2025-07-02 06:41:18.081             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.081             atags = btags = ""
2025-07-02 06:41:18.081             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.081             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.081                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.081                 if tag == 'replace':
2025-07-02 06:41:18.081                     atags += '^' * la
2025-07-02 06:41:18.081                     btags += '^' * lb
2025-07-02 06:41:18.081                 elif tag == 'delete':
2025-07-02 06:41:18.082                     atags += '-' * la
2025-07-02 06:41:18.082                 elif tag == 'insert':
2025-07-02 06:41:18.082                     btags += '+' * lb
2025-07-02 06:41:18.082                 elif tag == 'equal':
2025-07-02 06:41:18.082                     atags += ' ' * la
2025-07-02 06:41:18.082                     btags += ' ' * lb
2025-07-02 06:41:18.082                 else:
2025-07-02 06:41:18.082                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.082             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.082         else:
2025-07-02 06:41:18.082             # the synch pair is identical
2025-07-02 06:41:18.082             yield '  ' + aelt
2025-07-02 06:41:18.082
2025-07-02 06:41:18.082         # pump out diffs from after the synch point
2025-07-02 06:41:18.082 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.082
2025-07-02 06:41:18.082 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.082 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.082
2025-07-02 06:41:18.082 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.083 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.083 alo = 340, ahi = 1101
2025-07-02 06:41:18.083 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.083 blo = 340, bhi = 1101
2025-07-02 06:41:18.083
2025-07-02 06:41:18.083     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.083         g = []
2025-07-02 06:41:18.083         if alo < ahi:
2025-07-02 06:41:18.083             if blo < bhi:
2025-07-02 06:41:18.083                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.083             else:
2025-07-02 06:41:18.083                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.083         elif blo < bhi:
2025-07-02 06:41:18.083             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.083
2025-07-02 06:41:18.083 >       yield from g
2025-07-02 06:41:18.083
2025-07-02 06:41:18.084 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.084 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.084
2025-07-02 06:41:18.084 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.084 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.084 alo = 340, ahi = 1101
2025-07-02 06:41:18.084 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.084 blo = 340, bhi = 1101
2025-07-02 06:41:18.084
2025-07-02 06:41:18.084     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.084         r"""
2025-07-02 06:41:18.084         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.084         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.084         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.084         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.084
2025-07-02 06:41:18.084         Example:
2025-07-02 06:41:18.084
2025-07-02 06:41:18.084         >>> d = Differ()
2025-07-02 06:41:18.085         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.085         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.085         >>> print(''.join(results), end="")
2025-07-02 06:41:18.085         - abcDefghiJkl
2025-07-02 06:41:18.085         + abcdefGhijkl
2025-07-02 06:41:18.085         """
2025-07-02 06:41:18.085
2025-07-02 06:41:18.085         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.085         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.085         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.085         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.085         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.085
2025-07-02 06:41:18.085         # search for the pair that matches best without being identical
2025-07-02 06:41:18.085         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.085         # on junk -- unless we have to)
2025-07-02 06:41:18.085         for j in range(blo, bhi):
2025-07-02 06:41:18.085             bj = b[j]
2025-07-02 06:41:18.086             cruncher.set_seq2(bj)
2025-07-02 06:41:18.086             for i in range(alo, ahi):
2025-07-02 06:41:18.086                 ai = a[i]
2025-07-02 06:41:18.086                 if ai == bj:
2025-07-02 06:41:18.086                     if eqi is None:
2025-07-02 06:41:18.086                         eqi, eqj = i, j
2025-07-02 06:41:18.086                     continue
2025-07-02 06:41:18.086                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.086                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.086                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.086                 # compares by a factor of 3.
2025-07-02 06:41:18.086                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.086                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.086                 # of the computation is cached by cruncher
2025-07-02 06:41:18.086                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.086                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.086                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.086                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.086         if best_ratio < cutoff:
2025-07-02 06:41:18.086             # no non-identical "pretty close" pair
2025-07-02 06:41:18.087             if eqi is None:
2025-07-02 06:41:18.087                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.087                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.087                 return
2025-07-02 06:41:18.087             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.087             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.087         else:
2025-07-02 06:41:18.087             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.087             eqi = None
2025-07-02 06:41:18.087
2025-07-02 06:41:18.087         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.087         # identical
2025-07-02 06:41:18.087
2025-07-02 06:41:18.087         # pump out diffs from before the synch point
2025-07-02 06:41:18.087         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.087
2025-07-02 06:41:18.087         # do intraline marking on the synch pair
2025-07-02 06:41:18.087         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.087         if eqi is None:
2025-07-02 06:41:18.087             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.088             atags = btags = ""
2025-07-02 06:41:18.088             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.088             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.088                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.088                 if tag == 'replace':
2025-07-02 06:41:18.088                     atags += '^' * la
2025-07-02 06:41:18.088                     btags += '^' * lb
2025-07-02 06:41:18.088                 elif tag == 'delete':
2025-07-02 06:41:18.088                     atags += '-' * la
2025-07-02 06:41:18.088                 elif tag == 'insert':
2025-07-02 06:41:18.088                     btags += '+' * lb
2025-07-02 06:41:18.088                 elif tag == 'equal':
2025-07-02 06:41:18.088                     atags += ' ' * la
2025-07-02 06:41:18.088                     btags += ' ' * lb
2025-07-02 06:41:18.088                 else:
2025-07-02 06:41:18.088                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.088             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.088         else:
2025-07-02 06:41:18.088             # the synch pair is identical
2025-07-02 06:41:18.088             yield '  ' + aelt
2025-07-02 06:41:18.088
2025-07-02 06:41:18.089         # pump out diffs from after the synch point
2025-07-02 06:41:18.089 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.089
2025-07-02 06:41:18.089 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.089 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.089
2025-07-02 06:41:18.089 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.089 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.089 alo = 341, ahi = 1101
2025-07-02 06:41:18.089 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.089 blo = 341, bhi = 1101
2025-07-02 06:41:18.089
2025-07-02 06:41:18.089     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.089         g = []
2025-07-02 06:41:18.089         if alo < ahi:
2025-07-02 06:41:18.089             if blo < bhi:
2025-07-02 06:41:18.089                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.089             else:
2025-07-02 06:41:18.090                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.090         elif blo < bhi:
2025-07-02 06:41:18.090             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.090
2025-07-02 06:41:18.090 >       yield from g
2025-07-02 06:41:18.090
2025-07-02 06:41:18.090 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.090 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.090
2025-07-02 06:41:18.090 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.090 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.090 alo = 341, ahi = 1101
2025-07-02 06:41:18.090 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.090 blo = 341, bhi = 1101
2025-07-02 06:41:18.090
2025-07-02 06:41:18.090     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.090         r"""
2025-07-02 06:41:18.090         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.090         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.090         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.091         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.091
2025-07-02 06:41:18.091         Example:
2025-07-02 06:41:18.091
2025-07-02 06:41:18.091         >>> d = Differ()
2025-07-02 06:41:18.091         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.091         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.091         >>> print(''.join(results), end="")
2025-07-02 06:41:18.091         - abcDefghiJkl
2025-07-02 06:41:18.091         + abcdefGhijkl
2025-07-02 06:41:18.091         """
2025-07-02 06:41:18.091
2025-07-02 06:41:18.091         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.091         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.091         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.091         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.091         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.092
2025-07-02 06:41:18.092         # search for the pair that matches best without being identical
2025-07-02 06:41:18.092         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.092         # on junk -- unless we have to)
2025-07-02 06:41:18.092         for j in range(blo, bhi):
2025-07-02 06:41:18.092             bj = b[j]
2025-07-02 06:41:18.092             cruncher.set_seq2(bj)
2025-07-02 06:41:18.092             for i in range(alo, ahi):
2025-07-02 06:41:18.092                 ai = a[i]
2025-07-02 06:41:18.092                 if ai == bj:
2025-07-02 06:41:18.092                     if eqi is None:
2025-07-02 06:41:18.092                         eqi, eqj = i, j
2025-07-02 06:41:18.092                     continue
2025-07-02 06:41:18.092                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.092                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.092                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.092                 # compares by a factor of 3.
2025-07-02 06:41:18.092                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.092                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.092                 # of the computation is cached by cruncher
2025-07-02 06:41:18.093                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.093                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.093                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.093                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.093         if best_ratio < cutoff:
2025-07-02 06:41:18.093             # no non-identical "pretty close" pair
2025-07-02 06:41:18.093             if eqi is None:
2025-07-02 06:41:18.093                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.093                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.093                 return
2025-07-02 06:41:18.093             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.093             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.093         else:
2025-07-02 06:41:18.093             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.093             eqi = None
2025-07-02 06:41:18.093
2025-07-02 06:41:18.093         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.093         # identical
2025-07-02 06:41:18.093
2025-07-02 06:41:18.094         # pump out diffs from before the synch point
2025-07-02 06:41:18.094         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.094
2025-07-02 06:41:18.094         # do intraline marking on the synch pair
2025-07-02 06:41:18.094         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.094         if eqi is None:
2025-07-02 06:41:18.094             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.094             atags = btags = ""
2025-07-02 06:41:18.094             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.094             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.094                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.094                 if tag == 'replace':
2025-07-02 06:41:18.094                     atags += '^' * la
2025-07-02 06:41:18.094                     btags += '^' * lb
2025-07-02 06:41:18.094                 elif tag == 'delete':
2025-07-02 06:41:18.094                     atags += '-' * la
2025-07-02 06:41:18.094                 elif tag == 'insert':
2025-07-02 06:41:18.094                     btags += '+' * lb
2025-07-02 06:41:18.094                 elif tag == 'equal':
2025-07-02 06:41:18.094                     atags += ' ' * la
2025-07-02 06:41:18.095                     btags += ' ' * lb
2025-07-02 06:41:18.095                 else:
2025-07-02 06:41:18.095                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.095             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.095         else:
2025-07-02 06:41:18.095             # the synch pair is identical
2025-07-02 06:41:18.095             yield '  ' + aelt
2025-07-02 06:41:18.095
2025-07-02 06:41:18.095         # pump out diffs from after the synch point
2025-07-02 06:41:18.095 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.095
2025-07-02 06:41:18.095 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.095 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.095
2025-07-02 06:41:18.095 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.095 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.095 alo = 342, ahi = 1101
2025-07-02 06:41:18.095 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.095 blo = 342, bhi = 1101
2025-07-02 06:41:18.095
2025-07-02 06:41:18.096     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.096         g = []
2025-07-02 06:41:18.096         if alo < ahi:
2025-07-02 06:41:18.096             if blo < bhi:
2025-07-02 06:41:18.096                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.096             else:
2025-07-02 06:41:18.096                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.096         elif blo < bhi:
2025-07-02 06:41:18.096             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.096
2025-07-02 06:41:18.096 >       yield from g
2025-07-02 06:41:18.096
2025-07-02 06:41:18.096 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.096 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.096
2025-07-02 06:41:18.096 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.096 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.096 alo = 342, ahi = 1101
2025-07-02 06:41:18.096 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.096 blo = 342, bhi = 1101
2025-07-02 06:41:18.096
2025-07-02 06:41:18.097     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.097         r"""
2025-07-02 06:41:18.097         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.097         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.097         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.097         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.097
2025-07-02 06:41:18.097         Example:
2025-07-02 06:41:18.097
2025-07-02 06:41:18.097         >>> d = Differ()
2025-07-02 06:41:18.097         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.097         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.097         >>> print(''.join(results), end="")
2025-07-02 06:41:18.097         - abcDefghiJkl
2025-07-02 06:41:18.097         + abcdefGhijkl
2025-07-02 06:41:18.097         """
2025-07-02 06:41:18.097
2025-07-02 06:41:18.097         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.098         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.098         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.098         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.098         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.098
2025-07-02 06:41:18.098         # search for the pair that matches best without being identical
2025-07-02 06:41:18.098         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.098         # on junk -- unless we have to)
2025-07-02 06:41:18.098         for j in range(blo, bhi):
2025-07-02 06:41:18.098             bj = b[j]
2025-07-02 06:41:18.098             cruncher.set_seq2(bj)
2025-07-02 06:41:18.098             for i in range(alo, ahi):
2025-07-02 06:41:18.098                 ai = a[i]
2025-07-02 06:41:18.098                 if ai == bj:
2025-07-02 06:41:18.098                     if eqi is None:
2025-07-02 06:41:18.098                         eqi, eqj = i, j
2025-07-02 06:41:18.098                     continue
2025-07-02 06:41:18.098                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.098                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.098                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.099                 # compares by a factor of 3.
2025-07-02 06:41:18.099                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.099                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.099                 # of the computation is cached by cruncher
2025-07-02 06:41:18.099                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.099                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.099                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.099                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.099         if best_ratio < cutoff:
2025-07-02 06:41:18.099             # no non-identical "pretty close" pair
2025-07-02 06:41:18.099             if eqi is None:
2025-07-02 06:41:18.099                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.099                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.099                 return
2025-07-02 06:41:18.099             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.099             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.099         else:
2025-07-02 06:41:18.099             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.099             eqi = None
2025-07-02 06:41:18.099
2025-07-02 06:41:18.099         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.100         # identical
2025-07-02 06:41:18.100
2025-07-02 06:41:18.100         # pump out diffs from before the synch point
2025-07-02 06:41:18.100         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.100
2025-07-02 06:41:18.100         # do intraline marking on the synch pair
2025-07-02 06:41:18.100         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.100         if eqi is None:
2025-07-02 06:41:18.100             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.100             atags = btags = ""
2025-07-02 06:41:18.100             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.100             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.100                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.100                 if tag == 'replace':
2025-07-02 06:41:18.100                     atags += '^' * la
2025-07-02 06:41:18.100                     btags += '^' * lb
2025-07-02 06:41:18.100                 elif tag == 'delete':
2025-07-02 06:41:18.100                     atags += '-' * la
2025-07-02 06:41:18.100                 elif tag == 'insert':
2025-07-02 06:41:18.101                     btags += '+' * lb
2025-07-02 06:41:18.101                 elif tag == 'equal':
2025-07-02 06:41:18.101                     atags += ' ' * la
2025-07-02 06:41:18.101                     btags += ' ' * lb
2025-07-02 06:41:18.101                 else:
2025-07-02 06:41:18.101                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.101             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.101         else:
2025-07-02 06:41:18.101             # the synch pair is identical
2025-07-02 06:41:18.101             yield '  ' + aelt
2025-07-02 06:41:18.101
2025-07-02 06:41:18.101         # pump out diffs from after the synch point
2025-07-02 06:41:18.101 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.101
2025-07-02 06:41:18.101 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.101 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.101
2025-07-02 06:41:18.101 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.101 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.102 alo = 343, ahi = 1101
2025-07-02 06:41:18.102 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.102 blo = 343, bhi = 1101
2025-07-02 06:41:18.102
2025-07-02 06:41:18.102     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.102         g = []
2025-07-02 06:41:18.102         if alo < ahi:
2025-07-02 06:41:18.102             if blo < bhi:
2025-07-02 06:41:18.102                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.102             else:
2025-07-02 06:41:18.102                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.102         elif blo < bhi:
2025-07-02 06:41:18.102             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.102
2025-07-02 06:41:18.102 >       yield from g
2025-07-02 06:41:18.102
2025-07-02 06:41:18.102 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.102 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.102
2025-07-02 06:41:18.102 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.103 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.103 alo = 343, ahi = 1101
2025-07-02 06:41:18.103 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.103 blo = 343, bhi = 1101
2025-07-02 06:41:18.103
2025-07-02 06:41:18.103     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.103         r"""
2025-07-02 06:41:18.103         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.103         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.103         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.103         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.103
2025-07-02 06:41:18.103         Example:
2025-07-02 06:41:18.103
2025-07-02 06:41:18.103         >>> d = Differ()
2025-07-02 06:41:18.103         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.103         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.103         >>> print(''.join(results), end="")
2025-07-02 06:41:18.103         - abcDefghiJkl
2025-07-02 06:41:18.104         + abcdefGhijkl
2025-07-02 06:41:18.104         """
2025-07-02 06:41:18.104
2025-07-02 06:41:18.104         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.104         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.104         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.104         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.104         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.104
2025-07-02 06:41:18.104         # search for the pair that matches best without being identical
2025-07-02 06:41:18.104         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.104         # on junk -- unless we have to)
2025-07-02 06:41:18.104         for j in range(blo, bhi):
2025-07-02 06:41:18.104             bj = b[j]
2025-07-02 06:41:18.104             cruncher.set_seq2(bj)
2025-07-02 06:41:18.104             for i in range(alo, ahi):
2025-07-02 06:41:18.104                 ai = a[i]
2025-07-02 06:41:18.104                 if ai == bj:
2025-07-02 06:41:18.104                     if eqi is None:
2025-07-02 06:41:18.104                         eqi, eqj = i, j
2025-07-02 06:41:18.105                     continue
2025-07-02 06:41:18.105                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.105                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.105                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.105                 # compares by a factor of 3.
2025-07-02 06:41:18.105                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.105                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.105                 # of the computation is cached by cruncher
2025-07-02 06:41:18.105                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.105                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.105                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.105                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.105         if best_ratio < cutoff:
2025-07-02 06:41:18.105             # no non-identical "pretty close" pair
2025-07-02 06:41:18.105             if eqi is None:
2025-07-02 06:41:18.105                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.105                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.106                 return
2025-07-02 06:41:18.106             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.106             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.106         else:
2025-07-02 06:41:18.106             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.106             eqi = None
2025-07-02 06:41:18.106
2025-07-02 06:41:18.106         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.106         # identical
2025-07-02 06:41:18.106
2025-07-02 06:41:18.106         # pump out diffs from before the synch point
2025-07-02 06:41:18.106         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.106
2025-07-02 06:41:18.106         # do intraline marking on the synch pair
2025-07-02 06:41:18.106         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.106         if eqi is None:
2025-07-02 06:41:18.106             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.106             atags = btags = ""
2025-07-02 06:41:18.106             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.106             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.107                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.107                 if tag == 'replace':
2025-07-02 06:41:18.107                     atags += '^' * la
2025-07-02 06:41:18.107                     btags += '^' * lb
2025-07-02 06:41:18.107                 elif tag == 'delete':
2025-07-02 06:41:18.107                     atags += '-' * la
2025-07-02 06:41:18.107                 elif tag == 'insert':
2025-07-02 06:41:18.107                     btags += '+' * lb
2025-07-02 06:41:18.107                 elif tag == 'equal':
2025-07-02 06:41:18.107                     atags += ' ' * la
2025-07-02 06:41:18.107                     btags += ' ' * lb
2025-07-02 06:41:18.107                 else:
2025-07-02 06:41:18.107                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.107             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.107         else:
2025-07-02 06:41:18.107             # the synch pair is identical
2025-07-02 06:41:18.107             yield '  ' + aelt
2025-07-02 06:41:18.107
2025-07-02 06:41:18.107         # pump out diffs from after the synch point
2025-07-02 06:41:18.107 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.108
2025-07-02 06:41:18.108 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.108 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.108
2025-07-02 06:41:18.108 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.108 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.108 alo = 344, ahi = 1101
2025-07-02 06:41:18.108 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.108 blo = 344, bhi = 1101
2025-07-02 06:41:18.108
2025-07-02 06:41:18.108     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.108         g = []
2025-07-02 06:41:18.108         if alo < ahi:
2025-07-02 06:41:18.108             if blo < bhi:
2025-07-02 06:41:18.108                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.108             else:
2025-07-02 06:41:18.108                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.108         elif blo < bhi:
2025-07-02 06:41:18.108             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.109
2025-07-02 06:41:18.109 >       yield from g
2025-07-02 06:41:18.109
2025-07-02 06:41:18.109 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.109 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.109
2025-07-02 06:41:18.109 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.109 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.109 alo = 344, ahi = 1101
2025-07-02 06:41:18.109 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.109 blo = 344, bhi = 1101
2025-07-02 06:41:18.109
2025-07-02 06:41:18.109     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.109         r"""
2025-07-02 06:41:18.109         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.109         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.109         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.109         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.110
2025-07-02 06:41:18.110         Example:
2025-07-02 06:41:18.110
2025-07-02 06:41:18.110         >>> d = Differ()
2025-07-02 06:41:18.110         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.110         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.110         >>> print(''.join(results), end="")
2025-07-02 06:41:18.110         - abcDefghiJkl
2025-07-02 06:41:18.110         + abcdefGhijkl
2025-07-02 06:41:18.110         """
2025-07-02 06:41:18.110
2025-07-02 06:41:18.110         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.110         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.110         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.110         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.110         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.110
2025-07-02 06:41:18.111         # search for the pair that matches best without being identical
2025-07-02 06:41:18.111         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.111         # on junk -- unless we have to)
2025-07-02 06:41:18.111         for j in range(blo, bhi):
2025-07-02 06:41:18.111             bj = b[j]
2025-07-02 06:41:18.111             cruncher.set_seq2(bj)
2025-07-02 06:41:18.111             for i in range(alo, ahi):
2025-07-02 06:41:18.111                 ai = a[i]
2025-07-02 06:41:18.111                 if ai == bj:
2025-07-02 06:41:18.111                     if eqi is None:
2025-07-02 06:41:18.111                         eqi, eqj = i, j
2025-07-02 06:41:18.111                     continue
2025-07-02 06:41:18.111                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.111                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.111                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.111                 # compares by a factor of 3.
2025-07-02 06:41:18.111                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.111                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.111                 # of the computation is cached by cruncher
2025-07-02 06:41:18.111                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.112                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.112                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.112                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.112         if best_ratio < cutoff:
2025-07-02 06:41:18.112             # no non-identical "pretty close" pair
2025-07-02 06:41:18.112             if eqi is None:
2025-07-02 06:41:18.112                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.112                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.112                 return
2025-07-02 06:41:18.112             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.112             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.112         else:
2025-07-02 06:41:18.112             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.112             eqi = None
2025-07-02 06:41:18.112
2025-07-02 06:41:18.112         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.112         # identical
2025-07-02 06:41:18.112
2025-07-02 06:41:18.112         # pump out diffs from before the synch point
2025-07-02 06:41:18.112         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.113
2025-07-02 06:41:18.113         # do intraline marking on the synch pair
2025-07-02 06:41:18.113         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.113         if eqi is None:
2025-07-02 06:41:18.113             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.113             atags = btags = ""
2025-07-02 06:41:18.113             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.113             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.113                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.113                 if tag == 'replace':
2025-07-02 06:41:18.113                     atags += '^' * la
2025-07-02 06:41:18.113                     btags += '^' * lb
2025-07-02 06:41:18.113                 elif tag == 'delete':
2025-07-02 06:41:18.113                     atags += '-' * la
2025-07-02 06:41:18.113                 elif tag == 'insert':
2025-07-02 06:41:18.113                     btags += '+' * lb
2025-07-02 06:41:18.113                 elif tag == 'equal':
2025-07-02 06:41:18.113                     atags += ' ' * la
2025-07-02 06:41:18.113                     btags += ' ' * lb
2025-07-02 06:41:18.113                 else:
2025-07-02 06:41:18.114                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.114             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.114         else:
2025-07-02 06:41:18.114             # the synch pair is identical
2025-07-02 06:41:18.114             yield '  ' + aelt
2025-07-02 06:41:18.114
2025-07-02 06:41:18.114         # pump out diffs from after the synch point
2025-07-02 06:41:18.114 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.114
2025-07-02 06:41:18.114 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.114 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.114
2025-07-02 06:41:18.114 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.114 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.114 alo = 345, ahi = 1101
2025-07-02 06:41:18.114 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.114 blo = 345, bhi = 1101
2025-07-02 06:41:18.114
2025-07-02 06:41:18.114     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.115         g = []
2025-07-02 06:41:18.115         if alo < ahi:
2025-07-02 06:41:18.115             if blo < bhi:
2025-07-02 06:41:18.115                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.115             else:
2025-07-02 06:41:18.115                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.115         elif blo < bhi:
2025-07-02 06:41:18.115             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.115
2025-07-02 06:41:18.115 >       yield from g
2025-07-02 06:41:18.115
2025-07-02 06:41:18.115 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.115 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.115
2025-07-02 06:41:18.115 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.115 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.115 alo = 345, ahi = 1101
2025-07-02 06:41:18.115 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.115 blo = 345, bhi = 1101
2025-07-02 06:41:18.115
2025-07-02 06:41:18.116     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.116         r"""
2025-07-02 06:41:18.116         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.116         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.116         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.116         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.116
2025-07-02 06:41:18.116         Example:
2025-07-02 06:41:18.116
2025-07-02 06:41:18.116         >>> d = Differ()
2025-07-02 06:41:18.116         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.116         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.116         >>> print(''.join(results), end="")
2025-07-02 06:41:18.116         - abcDefghiJkl
2025-07-02 06:41:18.116         + abcdefGhijkl
2025-07-02 06:41:18.116         """
2025-07-02 06:41:18.116
2025-07-02 06:41:18.116         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.116         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.117         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.117         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.117         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.117
2025-07-02 06:41:18.117         # search for the pair that matches best without being identical
2025-07-02 06:41:18.117         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.117         # on junk -- unless we have to)
2025-07-02 06:41:18.117         for j in range(blo, bhi):
2025-07-02 06:41:18.117             bj = b[j]
2025-07-02 06:41:18.117             cruncher.set_seq2(bj)
2025-07-02 06:41:18.117             for i in range(alo, ahi):
2025-07-02 06:41:18.117                 ai = a[i]
2025-07-02 06:41:18.117                 if ai == bj:
2025-07-02 06:41:18.117                     if eqi is None:
2025-07-02 06:41:18.117                         eqi, eqj = i, j
2025-07-02 06:41:18.117                     continue
2025-07-02 06:41:18.117                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.117                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.117                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.117                 # compares by a factor of 3.
2025-07-02 06:41:18.118                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.118                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.118                 # of the computation is cached by cruncher
2025-07-02 06:41:18.118                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.118                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.118                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.118                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.118         if best_ratio < cutoff:
2025-07-02 06:41:18.118             # no non-identical "pretty close" pair
2025-07-02 06:41:18.118             if eqi is None:
2025-07-02 06:41:18.118                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.118                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.118                 return
2025-07-02 06:41:18.118             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.118             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.118         else:
2025-07-02 06:41:18.118             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.119             eqi = None
2025-07-02 06:41:18.119
2025-07-02 06:41:18.119         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.119         # identical
2025-07-02 06:41:18.119
2025-07-02 06:41:18.119         # pump out diffs from before the synch point
2025-07-02 06:41:18.119         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.119
2025-07-02 06:41:18.119         # do intraline marking on the synch pair
2025-07-02 06:41:18.119         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.119         if eqi is None:
2025-07-02 06:41:18.119             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.119             atags = btags = ""
2025-07-02 06:41:18.119             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.119             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.119                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.119                 if tag == 'replace':
2025-07-02 06:41:18.119                     atags += '^' * la
2025-07-02 06:41:18.119                     btags += '^' * lb
2025-07-02 06:41:18.120                 elif tag == 'delete':
2025-07-02 06:41:18.120                     atags += '-' * la
2025-07-02 06:41:18.120                 elif tag == 'insert':
2025-07-02 06:41:18.120                     btags += '+' * lb
2025-07-02 06:41:18.120                 elif tag == 'equal':
2025-07-02 06:41:18.120                     atags += ' ' * la
2025-07-02 06:41:18.120                     btags += ' ' * lb
2025-07-02 06:41:18.120                 else:
2025-07-02 06:41:18.120                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.120             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.120         else:
2025-07-02 06:41:18.120             # the synch pair is identical
2025-07-02 06:41:18.120             yield '  ' + aelt
2025-07-02 06:41:18.120
2025-07-02 06:41:18.120         # pump out diffs from after the synch point
2025-07-02 06:41:18.120 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.120
2025-07-02 06:41:18.120 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.120 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.120
2025-07-02 06:41:18.121 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.121 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.121 alo = 346, ahi = 1101
2025-07-02 06:41:18.121 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.121 blo = 346, bhi = 1101
2025-07-02 06:41:18.121
2025-07-02 06:41:18.121     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.121         g = []
2025-07-02 06:41:18.121         if alo < ahi:
2025-07-02 06:41:18.121             if blo < bhi:
2025-07-02 06:41:18.121                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.121             else:
2025-07-02 06:41:18.121                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.121         elif blo < bhi:
2025-07-02 06:41:18.121             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.121
2025-07-02 06:41:18.121 >       yield from g
2025-07-02 06:41:18.121
2025-07-02 06:41:18.122 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.122 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.122
2025-07-02 06:41:18.122 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.122 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.122 alo = 346, ahi = 1101
2025-07-02 06:41:18.122 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.122 blo = 346, bhi = 1101
2025-07-02 06:41:18.122
2025-07-02 06:41:18.122     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.122         r"""
2025-07-02 06:41:18.122         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.122         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.122         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.122         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.122
2025-07-02 06:41:18.122         Example:
2025-07-02 06:41:18.122
2025-07-02 06:41:18.122         >>> d = Differ()
2025-07-02 06:41:18.123         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.123         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.123         >>> print(''.join(results), end="")
2025-07-02 06:41:18.123         - abcDefghiJkl
2025-07-02 06:41:18.123         + abcdefGhijkl
2025-07-02 06:41:18.123         """
2025-07-02 06:41:18.123
2025-07-02 06:41:18.123         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.123         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.123         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.123         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.123         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.123
2025-07-02 06:41:18.123         # search for the pair that matches best without being identical
2025-07-02 06:41:18.123         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.123         # on junk -- unless we have to)
2025-07-02 06:41:18.123         for j in range(blo, bhi):
2025-07-02 06:41:18.123             bj = b[j]
2025-07-02 06:41:18.124             cruncher.set_seq2(bj)
2025-07-02 06:41:18.124             for i in range(alo, ahi):
2025-07-02 06:41:18.124                 ai = a[i]
2025-07-02 06:41:18.124                 if ai == bj:
2025-07-02 06:41:18.124                     if eqi is None:
2025-07-02 06:41:18.124                         eqi, eqj = i, j
2025-07-02 06:41:18.124                     continue
2025-07-02 06:41:18.124                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.124                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.124                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.124                 # compares by a factor of 3.
2025-07-02 06:41:18.124                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.124                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.124                 # of the computation is cached by cruncher
2025-07-02 06:41:18.124                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.124                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.124                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.124                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.124         if best_ratio < cutoff:
2025-07-02 06:41:18.124             # no non-identical "pretty close" pair
2025-07-02 06:41:18.125             if eqi is None:
2025-07-02 06:41:18.125                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.125                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.125                 return
2025-07-02 06:41:18.125             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.125             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.125         else:
2025-07-02 06:41:18.125             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.125             eqi = None
2025-07-02 06:41:18.125
2025-07-02 06:41:18.125         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.125         # identical
2025-07-02 06:41:18.125
2025-07-02 06:41:18.125         # pump out diffs from before the synch point
2025-07-02 06:41:18.125         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.125
2025-07-02 06:41:18.125         # do intraline marking on the synch pair
2025-07-02 06:41:18.125         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.125         if eqi is None:
2025-07-02 06:41:18.125             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.126             atags = btags = ""
2025-07-02 06:41:18.126             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.126             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.126                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.126                 if tag == 'replace':
2025-07-02 06:41:18.126                     atags += '^' * la
2025-07-02 06:41:18.126                     btags += '^' * lb
2025-07-02 06:41:18.126                 elif tag == 'delete':
2025-07-02 06:41:18.126                     atags += '-' * la
2025-07-02 06:41:18.126                 elif tag == 'insert':
2025-07-02 06:41:18.126                     btags += '+' * lb
2025-07-02 06:41:18.126                 elif tag == 'equal':
2025-07-02 06:41:18.126                     atags += ' ' * la
2025-07-02 06:41:18.126                     btags += ' ' * lb
2025-07-02 06:41:18.126                 else:
2025-07-02 06:41:18.126                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.126             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.126         else:
2025-07-02 06:41:18.126             # the synch pair is identical
2025-07-02 06:41:18.126             yield '  ' + aelt
2025-07-02 06:41:18.127
2025-07-02 06:41:18.127         # pump out diffs from after the synch point
2025-07-02 06:41:18.127 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.127
2025-07-02 06:41:18.127 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.127 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.127
2025-07-02 06:41:18.127 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.127 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.127 alo = 347, ahi = 1101
2025-07-02 06:41:18.127 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.127 blo = 347, bhi = 1101
2025-07-02 06:41:18.127
2025-07-02 06:41:18.127     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.127         g = []
2025-07-02 06:41:18.127         if alo < ahi:
2025-07-02 06:41:18.127             if blo < bhi:
2025-07-02 06:41:18.128                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.128             else:
2025-07-02 06:41:18.128                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.128         elif blo < bhi:
2025-07-02 06:41:18.128             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.128
2025-07-02 06:41:18.128 >       yield from g
2025-07-02 06:41:18.128
2025-07-02 06:41:18.128 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.128 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.128
2025-07-02 06:41:18.128 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.128 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.128 alo = 347, ahi = 1101
2025-07-02 06:41:18.128 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.128 blo = 347, bhi = 1101
2025-07-02 06:41:18.128
2025-07-02 06:41:18.128     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.128         r"""
2025-07-02 06:41:18.129         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.129         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.129         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.129         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.129
2025-07-02 06:41:18.129         Example:
2025-07-02 06:41:18.129
2025-07-02 06:41:18.129         >>> d = Differ()
2025-07-02 06:41:18.129         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.129         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.129         >>> print(''.join(results), end="")
2025-07-02 06:41:18.129         - abcDefghiJkl
2025-07-02 06:41:18.129         + abcdefGhijkl
2025-07-02 06:41:18.129         """
2025-07-02 06:41:18.129
2025-07-02 06:41:18.129         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.129         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.129         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.129         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.130         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.130
2025-07-02 06:41:18.130         # search for the pair that matches best without being identical
2025-07-02 06:41:18.130         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.130         # on junk -- unless we have to)
2025-07-02 06:41:18.130         for j in range(blo, bhi):
2025-07-02 06:41:18.130             bj = b[j]
2025-07-02 06:41:18.130             cruncher.set_seq2(bj)
2025-07-02 06:41:18.130             for i in range(alo, ahi):
2025-07-02 06:41:18.130                 ai = a[i]
2025-07-02 06:41:18.130                 if ai == bj:
2025-07-02 06:41:18.130                     if eqi is None:
2025-07-02 06:41:18.130                         eqi, eqj = i, j
2025-07-02 06:41:18.130                     continue
2025-07-02 06:41:18.130                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.130                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.130                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.130                 # compares by a factor of 3.
2025-07-02 06:41:18.130                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.130                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.131                 # of the computation is cached by cruncher
2025-07-02 06:41:18.131                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.131                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.131                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.131                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.131         if best_ratio < cutoff:
2025-07-02 06:41:18.131             # no non-identical "pretty close" pair
2025-07-02 06:41:18.131             if eqi is None:
2025-07-02 06:41:18.131                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.131                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.131                 return
2025-07-02 06:41:18.131             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.131             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.131         else:
2025-07-02 06:41:18.131             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.131             eqi = None
2025-07-02 06:41:18.131
2025-07-02 06:41:18.131         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.131         # identical
2025-07-02 06:41:18.131
2025-07-02 06:41:18.132         # pump out diffs from before the synch point
2025-07-02 06:41:18.132         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.132
2025-07-02 06:41:18.132         # do intraline marking on the synch pair
2025-07-02 06:41:18.132         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.132         if eqi is None:
2025-07-02 06:41:18.132             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.132             atags = btags = ""
2025-07-02 06:41:18.132             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.132             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.132                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.132                 if tag == 'replace':
2025-07-02 06:41:18.132                     atags += '^' * la
2025-07-02 06:41:18.132                     btags += '^' * lb
2025-07-02 06:41:18.132                 elif tag == 'delete':
2025-07-02 06:41:18.132                     atags += '-' * la
2025-07-02 06:41:18.132                 elif tag == 'insert':
2025-07-02 06:41:18.132                     btags += '+' * lb
2025-07-02 06:41:18.132                 elif tag == 'equal':
2025-07-02 06:41:18.132                     atags += ' ' * la
2025-07-02 06:41:18.132                     btags += ' ' * lb
2025-07-02 06:41:18.133                 else:
2025-07-02 06:41:18.133                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.133             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.133         else:
2025-07-02 06:41:18.133             # the synch pair is identical
2025-07-02 06:41:18.133             yield '  ' + aelt
2025-07-02 06:41:18.133
2025-07-02 06:41:18.133         # pump out diffs from after the synch point
2025-07-02 06:41:18.133 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.133
2025-07-02 06:41:18.133 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.133 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.133
2025-07-02 06:41:18.133 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.133 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.133 alo = 348, ahi = 1101
2025-07-02 06:41:18.133 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.133 blo = 348, bhi = 1101
2025-07-02 06:41:18.133
2025-07-02 06:41:18.133     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.134         g = []
2025-07-02 06:41:18.134         if alo < ahi:
2025-07-02 06:41:18.134             if blo < bhi:
2025-07-02 06:41:18.134                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.134             else:
2025-07-02 06:41:18.134                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.134         elif blo < bhi:
2025-07-02 06:41:18.134             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.134
2025-07-02 06:41:18.134 >       yield from g
2025-07-02 06:41:18.134
2025-07-02 06:41:18.134 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.134 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.134
2025-07-02 06:41:18.134 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.134 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.134 alo = 348, ahi = 1101
2025-07-02 06:41:18.134 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.134 blo = 348, bhi = 1101
2025-07-02 06:41:18.134
2025-07-02 06:41:18.135     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.135         r"""
2025-07-02 06:41:18.135         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.135         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.135         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.135         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.135
2025-07-02 06:41:18.135         Example:
2025-07-02 06:41:18.135
2025-07-02 06:41:18.135         >>> d = Differ()
2025-07-02 06:41:18.135         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.135         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.135         >>> print(''.join(results), end="")
2025-07-02 06:41:18.135         - abcDefghiJkl
2025-07-02 06:41:18.135         + abcdefGhijkl
2025-07-02 06:41:18.135         """
2025-07-02 06:41:18.136
2025-07-02 06:41:18.136         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.136         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.136         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.136         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.136         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.136
2025-07-02 06:41:18.136         # search for the pair that matches best without being identical
2025-07-02 06:41:18.136         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.136         # on junk -- unless we have to)
2025-07-02 06:41:18.136         for j in range(blo, bhi):
2025-07-02 06:41:18.136             bj = b[j]
2025-07-02 06:41:18.136             cruncher.set_seq2(bj)
2025-07-02 06:41:18.136             for i in range(alo, ahi):
2025-07-02 06:41:18.136                 ai = a[i]
2025-07-02 06:41:18.136                 if ai == bj:
2025-07-02 06:41:18.136                     if eqi is None:
2025-07-02 06:41:18.136                         eqi, eqj = i, j
2025-07-02 06:41:18.136                     continue
2025-07-02 06:41:18.137                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.137                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.137                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.137                 # compares by a factor of 3.
2025-07-02 06:41:18.137                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.137                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.137                 # of the computation is cached by cruncher
2025-07-02 06:41:18.137                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.137                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.137                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.137                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.137         if best_ratio < cutoff:
2025-07-02 06:41:18.137             # no non-identical "pretty close" pair
2025-07-02 06:41:18.137             if eqi is None:
2025-07-02 06:41:18.137                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.137                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.137                 return
2025-07-02 06:41:18.137             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.137             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.138         else:
2025-07-02 06:41:18.138             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.138             eqi = None
2025-07-02 06:41:18.138
2025-07-02 06:41:18.138         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.138         # identical
2025-07-02 06:41:18.138
2025-07-02 06:41:18.138         # pump out diffs from before the synch point
2025-07-02 06:41:18.138         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.138
2025-07-02 06:41:18.138         # do intraline marking on the synch pair
2025-07-02 06:41:18.138         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.138         if eqi is None:
2025-07-02 06:41:18.138             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.138             atags = btags = ""
2025-07-02 06:41:18.138             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.138             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.138                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.138                 if tag == 'replace':
2025-07-02 06:41:18.138                     atags += '^' * la
2025-07-02 06:41:18.139                     btags += '^' * lb
2025-07-02 06:41:18.139                 elif tag == 'delete':
2025-07-02 06:41:18.139                     atags += '-' * la
2025-07-02 06:41:18.139                 elif tag == 'insert':
2025-07-02 06:41:18.139                     btags += '+' * lb
2025-07-02 06:41:18.139                 elif tag == 'equal':
2025-07-02 06:41:18.139                     atags += ' ' * la
2025-07-02 06:41:18.139                     btags += ' ' * lb
2025-07-02 06:41:18.139                 else:
2025-07-02 06:41:18.139                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.139             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.139         else:
2025-07-02 06:41:18.139             # the synch pair is identical
2025-07-02 06:41:18.139             yield '  ' + aelt
2025-07-02 06:41:18.139
2025-07-02 06:41:18.139         # pump out diffs from after the synch point
2025-07-02 06:41:18.139 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.139
2025-07-02 06:41:18.139 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.139 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.139
2025-07-02 06:41:18.139 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.139 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.140 alo = 349, ahi = 1101
2025-07-02 06:41:18.140 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.140 blo = 349, bhi = 1101
2025-07-02 06:41:18.140
2025-07-02 06:41:18.140     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.140         g = []
2025-07-02 06:41:18.140         if alo < ahi:
2025-07-02 06:41:18.140             if blo < bhi:
2025-07-02 06:41:18.140                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.140             else:
2025-07-02 06:41:18.140                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.140         elif blo < bhi:
2025-07-02 06:41:18.140             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.140
2025-07-02 06:41:18.140 >       yield from g
2025-07-02 06:41:18.140
2025-07-02 06:41:18.140 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.140 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.140
2025-07-02 06:41:18.140 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.140 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.141 alo = 349, ahi = 1101
2025-07-02 06:41:18.141 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.141 blo = 349, bhi = 1101
2025-07-02 06:41:18.141
2025-07-02 06:41:18.141     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.141         r"""
2025-07-02 06:41:18.141         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.141         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.141         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.141         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.141
2025-07-02 06:41:18.141         Example:
2025-07-02 06:41:18.141
2025-07-02 06:41:18.141         >>> d = Differ()
2025-07-02 06:41:18.141         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.141         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.141         >>> print(''.join(results), end="")
2025-07-02 06:41:18.141         - abcDefghiJkl
2025-07-02 06:41:18.141         + abcdefGhijkl
2025-07-02 06:41:18.142         """
2025-07-02 06:41:18.142
2025-07-02 06:41:18.142         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.142         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.142         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.142         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.142         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.142
2025-07-02 06:41:18.142         # search for the pair that matches best without being identical
2025-07-02 06:41:18.142         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.142         # on junk -- unless we have to)
2025-07-02 06:41:18.142         for j in range(blo, bhi):
2025-07-02 06:41:18.142             bj = b[j]
2025-07-02 06:41:18.142             cruncher.set_seq2(bj)
2025-07-02 06:41:18.142             for i in range(alo, ahi):
2025-07-02 06:41:18.142                 ai = a[i]
2025-07-02 06:41:18.142                 if ai == bj:
2025-07-02 06:41:18.142                     if eqi is None:
2025-07-02 06:41:18.142                         eqi, eqj = i, j
2025-07-02 06:41:18.143                     continue
2025-07-02 06:41:18.143                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.143                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.143                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.143                 # compares by a factor of 3.
2025-07-02 06:41:18.143                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.143                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.143                 # of the computation is cached by cruncher
2025-07-02 06:41:18.143                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.143                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.143                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.143                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.143         if best_ratio < cutoff:
2025-07-02 06:41:18.143             # no non-identical "pretty close" pair
2025-07-02 06:41:18.143             if eqi is None:
2025-07-02 06:41:18.143                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.143                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.143                 return
2025-07-02 06:41:18.143             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.143             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.144         else:
2025-07-02 06:41:18.144             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.144             eqi = None
2025-07-02 06:41:18.144
2025-07-02 06:41:18.144         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.144         # identical
2025-07-02 06:41:18.144
2025-07-02 06:41:18.144         # pump out diffs from before the synch point
2025-07-02 06:41:18.144         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.144
2025-07-02 06:41:18.144         # do intraline marking on the synch pair
2025-07-02 06:41:18.144         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.144         if eqi is None:
2025-07-02 06:41:18.144             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.144             atags = btags = ""
2025-07-02 06:41:18.144             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.144             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.144                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.145                 if tag == 'replace':
2025-07-02 06:41:18.145                     atags += '^' * la
2025-07-02 06:41:18.145                     btags += '^' * lb
2025-07-02 06:41:18.145                 elif tag == 'delete':
2025-07-02 06:41:18.145                     atags += '-' * la
2025-07-02 06:41:18.145                 elif tag == 'insert':
2025-07-02 06:41:18.145                     btags += '+' * lb
2025-07-02 06:41:18.145                 elif tag == 'equal':
2025-07-02 06:41:18.145                     atags += ' ' * la
2025-07-02 06:41:18.145                     btags += ' ' * lb
2025-07-02 06:41:18.145                 else:
2025-07-02 06:41:18.145                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.145             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.145         else:
2025-07-02 06:41:18.145             # the synch pair is identical
2025-07-02 06:41:18.145             yield '  ' + aelt
2025-07-02 06:41:18.145
2025-07-02 06:41:18.145         # pump out diffs from after the synch point
2025-07-02 06:41:18.145 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.145
2025-07-02 06:41:18.146 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.146 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.146
2025-07-02 06:41:18.146 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.146 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.146 alo = 350, ahi = 1101
2025-07-02 06:41:18.146 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.146 blo = 350, bhi = 1101
2025-07-02 06:41:18.146
2025-07-02 06:41:18.146     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.146         g = []
2025-07-02 06:41:18.146         if alo < ahi:
2025-07-02 06:41:18.146             if blo < bhi:
2025-07-02 06:41:18.146                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.146             else:
2025-07-02 06:41:18.146                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.146         elif blo < bhi:
2025-07-02 06:41:18.146             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.146
2025-07-02 06:41:18.147 >       yield from g
2025-07-02 06:41:18.147
2025-07-02 06:41:18.147 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.147 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.147
2025-07-02 06:41:18.147 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.147 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.147 alo = 350, ahi = 1101
2025-07-02 06:41:18.147 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.147 blo = 350, bhi = 1101
2025-07-02 06:41:18.147
2025-07-02 06:41:18.147     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.147         r"""
2025-07-02 06:41:18.147         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.147         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.147         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.147         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.147
2025-07-02 06:41:18.147         Example:
2025-07-02 06:41:18.148
2025-07-02 06:41:18.148         >>> d = Differ()
2025-07-02 06:41:18.148         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.148         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.148         >>> print(''.join(results), end="")
2025-07-02 06:41:18.148         - abcDefghiJkl
2025-07-02 06:41:18.148         + abcdefGhijkl
2025-07-02 06:41:18.148         """
2025-07-02 06:41:18.148
2025-07-02 06:41:18.148         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.148         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.148         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.148         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.148         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.148
2025-07-02 06:41:18.148         # search for the pair that matches best without being identical
2025-07-02 06:41:18.148         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.148         # on junk -- unless we have to)
2025-07-02 06:41:18.149         for j in range(blo, bhi):
2025-07-02 06:41:18.149             bj = b[j]
2025-07-02 06:41:18.149             cruncher.set_seq2(bj)
2025-07-02 06:41:18.149             for i in range(alo, ahi):
2025-07-02 06:41:18.149                 ai = a[i]
2025-07-02 06:41:18.149                 if ai == bj:
2025-07-02 06:41:18.149                     if eqi is None:
2025-07-02 06:41:18.149                         eqi, eqj = i, j
2025-07-02 06:41:18.149                     continue
2025-07-02 06:41:18.149                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.149                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.149                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.149                 # compares by a factor of 3.
2025-07-02 06:41:18.149                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.149                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.149                 # of the computation is cached by cruncher
2025-07-02 06:41:18.149                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.149                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.149                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.150                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.150         if best_ratio < cutoff:
2025-07-02 06:41:18.150             # no non-identical "pretty close" pair
2025-07-02 06:41:18.150             if eqi is None:
2025-07-02 06:41:18.150                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.150                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.150                 return
2025-07-02 06:41:18.150             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.150             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.150         else:
2025-07-02 06:41:18.150             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.150             eqi = None
2025-07-02 06:41:18.150
2025-07-02 06:41:18.150         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.150         # identical
2025-07-02 06:41:18.150
2025-07-02 06:41:18.150         # pump out diffs from before the synch point
2025-07-02 06:41:18.150         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.150
2025-07-02 06:41:18.150         # do intraline marking on the synch pair
2025-07-02 06:41:18.151         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.151         if eqi is None:
2025-07-02 06:41:18.151             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.151             atags = btags = ""
2025-07-02 06:41:18.151             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.151             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.151                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.151                 if tag == 'replace':
2025-07-02 06:41:18.151                     atags += '^' * la
2025-07-02 06:41:18.151                     btags += '^' * lb
2025-07-02 06:41:18.151                 elif tag == 'delete':
2025-07-02 06:41:18.151                     atags += '-' * la
2025-07-02 06:41:18.151                 elif tag == 'insert':
2025-07-02 06:41:18.151                     btags += '+' * lb
2025-07-02 06:41:18.151                 elif tag == 'equal':
2025-07-02 06:41:18.151                     atags += ' ' * la
2025-07-02 06:41:18.151                     btags += ' ' * lb
2025-07-02 06:41:18.151                 else:
2025-07-02 06:41:18.151                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.152             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.152         else:
2025-07-02 06:41:18.152             # the synch pair is identical
2025-07-02 06:41:18.152             yield '  ' + aelt
2025-07-02 06:41:18.152
2025-07-02 06:41:18.152         # pump out diffs from after the synch point
2025-07-02 06:41:18.152 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.152
2025-07-02 06:41:18.152 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.152 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.152
2025-07-02 06:41:18.152 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.152 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.152 alo = 351, ahi = 1101
2025-07-02 06:41:18.152 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.152 blo = 351, bhi = 1101
2025-07-02 06:41:18.152
2025-07-02 06:41:18.152     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.152         g = []
2025-07-02 06:41:18.153         if alo < ahi:
2025-07-02 06:41:18.153             if blo < bhi:
2025-07-02 06:41:18.153                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.153             else:
2025-07-02 06:41:18.153                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.153         elif blo < bhi:
2025-07-02 06:41:18.153             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.153
2025-07-02 06:41:18.153 >       yield from g
2025-07-02 06:41:18.153
2025-07-02 06:41:18.153 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.153 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.153
2025-07-02 06:41:18.153 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.153 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.153 alo = 351, ahi = 1101
2025-07-02 06:41:18.153 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.153 blo = 351, bhi = 1101
2025-07-02 06:41:18.154
2025-07-02 06:41:18.154     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.154         r"""
2025-07-02 06:41:18.154         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.154         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.154         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.154         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.154
2025-07-02 06:41:18.154         Example:
2025-07-02 06:41:18.154
2025-07-02 06:41:18.154         >>> d = Differ()
2025-07-02 06:41:18.154         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.154         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.154         >>> print(''.join(results), end="")
2025-07-02 06:41:18.154         - abcDefghiJkl
2025-07-02 06:41:18.154         + abcdefGhijkl
2025-07-02 06:41:18.154         """
2025-07-02 06:41:18.154
2025-07-02 06:41:18.155         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.155         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.155         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.155         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.155         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.155
2025-07-02 06:41:18.155         # search for the pair that matches best without being identical
2025-07-02 06:41:18.155         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.155         # on junk -- unless we have to)
2025-07-02 06:41:18.155         for j in range(blo, bhi):
2025-07-02 06:41:18.155             bj = b[j]
2025-07-02 06:41:18.155             cruncher.set_seq2(bj)
2025-07-02 06:41:18.155             for i in range(alo, ahi):
2025-07-02 06:41:18.155                 ai = a[i]
2025-07-02 06:41:18.155                 if ai == bj:
2025-07-02 06:41:18.155                     if eqi is None:
2025-07-02 06:41:18.155                         eqi, eqj = i, j
2025-07-02 06:41:18.155                     continue
2025-07-02 06:41:18.155                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.155                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.156                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.156                 # compares by a factor of 3.
2025-07-02 06:41:18.156                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.156                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.156                 # of the computation is cached by cruncher
2025-07-02 06:41:18.156                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.156                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.156                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.156                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.156         if best_ratio < cutoff:
2025-07-02 06:41:18.156             # no non-identical "pretty close" pair
2025-07-02 06:41:18.156             if eqi is None:
2025-07-02 06:41:18.156                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.156                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.156                 return
2025-07-02 06:41:18.156             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.156             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.156         else:
2025-07-02 06:41:18.156             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.157             eqi = None
2025-07-02 06:41:18.157
2025-07-02 06:41:18.157         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.157         # identical
2025-07-02 06:41:18.157
2025-07-02 06:41:18.157         # pump out diffs from before the synch point
2025-07-02 06:41:18.157         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.157
2025-07-02 06:41:18.157         # do intraline marking on the synch pair
2025-07-02 06:41:18.157         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.157         if eqi is None:
2025-07-02 06:41:18.157             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.157             atags = btags = ""
2025-07-02 06:41:18.157             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.157             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.157                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.157                 if tag == 'replace':
2025-07-02 06:41:18.157                     atags += '^' * la
2025-07-02 06:41:18.157                     btags += '^' * lb
2025-07-02 06:41:18.157                 elif tag == 'delete':
2025-07-02 06:41:18.158                     atags += '-' * la
2025-07-02 06:41:18.158                 elif tag == 'insert':
2025-07-02 06:41:18.158                     btags += '+' * lb
2025-07-02 06:41:18.158                 elif tag == 'equal':
2025-07-02 06:41:18.158                     atags += ' ' * la
2025-07-02 06:41:18.158                     btags += ' ' * lb
2025-07-02 06:41:18.158                 else:
2025-07-02 06:41:18.158                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.158             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.158         else:
2025-07-02 06:41:18.158             # the synch pair is identical
2025-07-02 06:41:18.158             yield '  ' + aelt
2025-07-02 06:41:18.158
2025-07-02 06:41:18.158         # pump out diffs from after the synch point
2025-07-02 06:41:18.158 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.158
2025-07-02 06:41:18.158 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.158 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.158
2025-07-02 06:41:18.159 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.159 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.159 alo = 352, ahi = 1101
2025-07-02 06:41:18.159 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.159 blo = 352, bhi = 1101
2025-07-02 06:41:18.159
2025-07-02 06:41:18.159     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.159         g = []
2025-07-02 06:41:18.159         if alo < ahi:
2025-07-02 06:41:18.159             if blo < bhi:
2025-07-02 06:41:18.159                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.159             else:
2025-07-02 06:41:18.159                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.159         elif blo < bhi:
2025-07-02 06:41:18.159             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.159
2025-07-02 06:41:18.159 >       yield from g
2025-07-02 06:41:18.159
2025-07-02 06:41:18.159 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.159 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.160
2025-07-02 06:41:18.160 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.160 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.160 alo = 352, ahi = 1101
2025-07-02 06:41:18.160 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.160 blo = 352, bhi = 1101
2025-07-02 06:41:18.160
2025-07-02 06:41:18.160     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.160         r"""
2025-07-02 06:41:18.160         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.160         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.160         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.160         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.160
2025-07-02 06:41:18.160         Example:
2025-07-02 06:41:18.160
2025-07-02 06:41:18.160         >>> d = Differ()
2025-07-02 06:41:18.160         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.160         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.161         >>> print(''.join(results), end="")
2025-07-02 06:41:18.161         - abcDefghiJkl
2025-07-02 06:41:18.161         + abcdefGhijkl
2025-07-02 06:41:18.161         """
2025-07-02 06:41:18.161
2025-07-02 06:41:18.161         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.161         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.161         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.161         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.161         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.161
2025-07-02 06:41:18.161         # search for the pair that matches best without being identical
2025-07-02 06:41:18.161         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.161         # on junk -- unless we have to)
2025-07-02 06:41:18.161         for j in range(blo, bhi):
2025-07-02 06:41:18.161             bj = b[j]
2025-07-02 06:41:18.161             cruncher.set_seq2(bj)
2025-07-02 06:41:18.161             for i in range(alo, ahi):
2025-07-02 06:41:18.162                 ai = a[i]
2025-07-02 06:41:18.162                 if ai == bj:
2025-07-02 06:41:18.162                     if eqi is None:
2025-07-02 06:41:18.162                         eqi, eqj = i, j
2025-07-02 06:41:18.162                     continue
2025-07-02 06:41:18.162                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.162                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.162                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.162                 # compares by a factor of 3.
2025-07-02 06:41:18.162                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.162                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.162                 # of the computation is cached by cruncher
2025-07-02 06:41:18.162                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.162                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.162                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.162                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.162         if best_ratio < cutoff:
2025-07-02 06:41:18.162             # no non-identical "pretty close" pair
2025-07-02 06:41:18.162             if eqi is None:
2025-07-02 06:41:18.163                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.163                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.163                 return
2025-07-02 06:41:18.163             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.163             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.163         else:
2025-07-02 06:41:18.163             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.163             eqi = None
2025-07-02 06:41:18.163
2025-07-02 06:41:18.163         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.163         # identical
2025-07-02 06:41:18.163
2025-07-02 06:41:18.163         # pump out diffs from before the synch point
2025-07-02 06:41:18.163         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.163
2025-07-02 06:41:18.163         # do intraline marking on the synch pair
2025-07-02 06:41:18.163         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.163         if eqi is None:
2025-07-02 06:41:18.163             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.164             atags = btags = ""
2025-07-02 06:41:18.164             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.164             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.164                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.164                 if tag == 'replace':
2025-07-02 06:41:18.164                     atags += '^' * la
2025-07-02 06:41:18.164                     btags += '^' * lb
2025-07-02 06:41:18.164                 elif tag == 'delete':
2025-07-02 06:41:18.164                     atags += '-' * la
2025-07-02 06:41:18.164                 elif tag == 'insert':
2025-07-02 06:41:18.164                     btags += '+' * lb
2025-07-02 06:41:18.164                 elif tag == 'equal':
2025-07-02 06:41:18.164                     atags += ' ' * la
2025-07-02 06:41:18.164                     btags += ' ' * lb
2025-07-02 06:41:18.164                 else:
2025-07-02 06:41:18.164                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.164             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.164         else:
2025-07-02 06:41:18.164             # the synch pair is identical
2025-07-02 06:41:18.164             yield '  ' + aelt
2025-07-02 06:41:18.165
2025-07-02 06:41:18.165         # pump out diffs from after the synch point
2025-07-02 06:41:18.165 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.165
2025-07-02 06:41:18.165 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.165 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.165
2025-07-02 06:41:18.165 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.165 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.165 alo = 353, ahi = 1101
2025-07-02 06:41:18.165 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.165 blo = 353, bhi = 1101
2025-07-02 06:41:18.165
2025-07-02 06:41:18.165     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.165         g = []
2025-07-02 06:41:18.165         if alo < ahi:
2025-07-02 06:41:18.165             if blo < bhi:
2025-07-02 06:41:18.165                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.165             else:
2025-07-02 06:41:18.166                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.166         elif blo < bhi:
2025-07-02 06:41:18.166             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.166
2025-07-02 06:41:18.166 >       yield from g
2025-07-02 06:41:18.166
2025-07-02 06:41:18.166 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.166 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.166
2025-07-02 06:41:18.166 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.166 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.166 alo = 353, ahi = 1101
2025-07-02 06:41:18.166 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.166 blo = 353, bhi = 1101
2025-07-02 06:41:18.166
2025-07-02 06:41:18.166     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.166         r"""
2025-07-02 06:41:18.166         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.166         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.167         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.167         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.167
2025-07-02 06:41:18.167         Example:
2025-07-02 06:41:18.167
2025-07-02 06:41:18.167         >>> d = Differ()
2025-07-02 06:41:18.167         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.167         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.167         >>> print(''.join(results), end="")
2025-07-02 06:41:18.167         - abcDefghiJkl
2025-07-02 06:41:18.167         + abcdefGhijkl
2025-07-02 06:41:18.167         """
2025-07-02 06:41:18.167
2025-07-02 06:41:18.167         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.167         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.167         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.167         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.167         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.168
2025-07-02 06:41:18.168         # search for the pair that matches best without being identical
2025-07-02 06:41:18.168         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.168         # on junk -- unless we have to)
2025-07-02 06:41:18.168         for j in range(blo, bhi):
2025-07-02 06:41:18.168             bj = b[j]
2025-07-02 06:41:18.168             cruncher.set_seq2(bj)
2025-07-02 06:41:18.168             for i in range(alo, ahi):
2025-07-02 06:41:18.168                 ai = a[i]
2025-07-02 06:41:18.168                 if ai == bj:
2025-07-02 06:41:18.168                     if eqi is None:
2025-07-02 06:41:18.168                         eqi, eqj = i, j
2025-07-02 06:41:18.168                     continue
2025-07-02 06:41:18.168                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.168                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.168                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.168                 # compares by a factor of 3.
2025-07-02 06:41:18.169                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.169                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.169                 # of the computation is cached by cruncher
2025-07-02 06:41:18.169                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.169                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.169                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.169                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.169         if best_ratio < cutoff:
2025-07-02 06:41:18.169             # no non-identical "pretty close" pair
2025-07-02 06:41:18.169             if eqi is None:
2025-07-02 06:41:18.169                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.169                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.169                 return
2025-07-02 06:41:18.169             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.169             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.169         else:
2025-07-02 06:41:18.169             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.169             eqi = None
2025-07-02 06:41:18.169
2025-07-02 06:41:18.170         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.170         # identical
2025-07-02 06:41:18.170
2025-07-02 06:41:18.170         # pump out diffs from before the synch point
2025-07-02 06:41:18.170         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.170
2025-07-02 06:41:18.170         # do intraline marking on the synch pair
2025-07-02 06:41:18.170         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.170         if eqi is None:
2025-07-02 06:41:18.170             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.170             atags = btags = ""
2025-07-02 06:41:18.170             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.170             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.170                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.170                 if tag == 'replace':
2025-07-02 06:41:18.170                     atags += '^' * la
2025-07-02 06:41:18.170                     btags += '^' * lb
2025-07-02 06:41:18.170                 elif tag == 'delete':
2025-07-02 06:41:18.170                     atags += '-' * la
2025-07-02 06:41:18.171                 elif tag == 'insert':
2025-07-02 06:41:18.171                     btags += '+' * lb
2025-07-02 06:41:18.171                 elif tag == 'equal':
2025-07-02 06:41:18.171                     atags += ' ' * la
2025-07-02 06:41:18.171                     btags += ' ' * lb
2025-07-02 06:41:18.171                 else:
2025-07-02 06:41:18.171                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.171             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.171         else:
2025-07-02 06:41:18.171             # the synch pair is identical
2025-07-02 06:41:18.171             yield '  ' + aelt
2025-07-02 06:41:18.171
2025-07-02 06:41:18.171         # pump out diffs from after the synch point
2025-07-02 06:41:18.171 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.171
2025-07-02 06:41:18.171 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.171 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.171
2025-07-02 06:41:18.171 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.172 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.172 alo = 356, ahi = 1101
2025-07-02 06:41:18.172 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.172 blo = 356, bhi = 1101
2025-07-02 06:41:18.172
2025-07-02 06:41:18.172     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.172         g = []
2025-07-02 06:41:18.172         if alo < ahi:
2025-07-02 06:41:18.172             if blo < bhi:
2025-07-02 06:41:18.172                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.172             else:
2025-07-02 06:41:18.172                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.172         elif blo < bhi:
2025-07-02 06:41:18.172             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.172
2025-07-02 06:41:18.172 >       yield from g
2025-07-02 06:41:18.172
2025-07-02 06:41:18.172 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.172 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.173
2025-07-02 06:41:18.173 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.173 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.173 alo = 356, ahi = 1101
2025-07-02 06:41:18.173 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.173 blo = 356, bhi = 1101
2025-07-02 06:41:18.173
2025-07-02 06:41:18.173     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.173         r"""
2025-07-02 06:41:18.173         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.173         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.173         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.173         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.173
2025-07-02 06:41:18.173         Example:
2025-07-02 06:41:18.173
2025-07-02 06:41:18.173         >>> d = Differ()
2025-07-02 06:41:18.173         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.173         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.174         >>> print(''.join(results), end="")
2025-07-02 06:41:18.174         - abcDefghiJkl
2025-07-02 06:41:18.174         + abcdefGhijkl
2025-07-02 06:41:18.174         """
2025-07-02 06:41:18.174
2025-07-02 06:41:18.174         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.174         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.174         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.174         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.174         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.174
2025-07-02 06:41:18.174         # search for the pair that matches best without being identical
2025-07-02 06:41:18.174         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.174         # on junk -- unless we have to)
2025-07-02 06:41:18.174         for j in range(blo, bhi):
2025-07-02 06:41:18.174             bj = b[j]
2025-07-02 06:41:18.174             cruncher.set_seq2(bj)
2025-07-02 06:41:18.175             for i in range(alo, ahi):
2025-07-02 06:41:18.175                 ai = a[i]
2025-07-02 06:41:18.175                 if ai == bj:
2025-07-02 06:41:18.175                     if eqi is None:
2025-07-02 06:41:18.175                         eqi, eqj = i, j
2025-07-02 06:41:18.175                     continue
2025-07-02 06:41:18.175                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.175                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.175                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.175                 # compares by a factor of 3.
2025-07-02 06:41:18.175                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.175                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.175                 # of the computation is cached by cruncher
2025-07-02 06:41:18.175                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.175                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.175                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.175                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.175         if best_ratio < cutoff:
2025-07-02 06:41:18.175             # no non-identical "pretty close" pair
2025-07-02 06:41:18.175             if eqi is None:
2025-07-02 06:41:18.176                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.176                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.176                 return
2025-07-02 06:41:18.176             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.176             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.176         else:
2025-07-02 06:41:18.176             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.176             eqi = None
2025-07-02 06:41:18.176
2025-07-02 06:41:18.176         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.176         # identical
2025-07-02 06:41:18.176
2025-07-02 06:41:18.176         # pump out diffs from before the synch point
2025-07-02 06:41:18.176         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.176
2025-07-02 06:41:18.176         # do intraline marking on the synch pair
2025-07-02 06:41:18.176         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.176         if eqi is None:
2025-07-02 06:41:18.176             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.177             atags = btags = ""
2025-07-02 06:41:18.177             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.177             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.177                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.177                 if tag == 'replace':
2025-07-02 06:41:18.177                     atags += '^' * la
2025-07-02 06:41:18.177                     btags += '^' * lb
2025-07-02 06:41:18.177                 elif tag == 'delete':
2025-07-02 06:41:18.177                     atags += '-' * la
2025-07-02 06:41:18.177                 elif tag == 'insert':
2025-07-02 06:41:18.177                     btags += '+' * lb
2025-07-02 06:41:18.177                 elif tag == 'equal':
2025-07-02 06:41:18.177                     atags += ' ' * la
2025-07-02 06:41:18.177                     btags += ' ' * lb
2025-07-02 06:41:18.177                 else:
2025-07-02 06:41:18.177                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.177             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.177         else:
2025-07-02 06:41:18.177             # the synch pair is identical
2025-07-02 06:41:18.178             yield '  ' + aelt
2025-07-02 06:41:18.178
2025-07-02 06:41:18.178         # pump out diffs from after the synch point
2025-07-02 06:41:18.178 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.178
2025-07-02 06:41:18.178 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.178 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.178
2025-07-02 06:41:18.178 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.178 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.178 alo = 357, ahi = 1101
2025-07-02 06:41:18.178 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.178 blo = 357, bhi = 1101
2025-07-02 06:41:18.178
2025-07-02 06:41:18.178     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.178         g = []
2025-07-02 06:41:18.178         if alo < ahi:
2025-07-02 06:41:18.178             if blo < bhi:
2025-07-02 06:41:18.178                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.178             else:
2025-07-02 06:41:18.179                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.179         elif blo < bhi:
2025-07-02 06:41:18.179             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.179
2025-07-02 06:41:18.179 >       yield from g
2025-07-02 06:41:18.179
2025-07-02 06:41:18.179 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.179 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.179
2025-07-02 06:41:18.179 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.179 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.179 alo = 357, ahi = 1101
2025-07-02 06:41:18.179 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.179 blo = 357, bhi = 1101
2025-07-02 06:41:18.179
2025-07-02 06:41:18.179     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.179         r"""
2025-07-02 06:41:18.179         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.180         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.180         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.180         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.180
2025-07-02 06:41:18.180         Example:
2025-07-02 06:41:18.180
2025-07-02 06:41:18.180         >>> d = Differ()
2025-07-02 06:41:18.180         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.180         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.180         >>> print(''.join(results), end="")
2025-07-02 06:41:18.180         - abcDefghiJkl
2025-07-02 06:41:18.180         + abcdefGhijkl
2025-07-02 06:41:18.180         """
2025-07-02 06:41:18.180
2025-07-02 06:41:18.180         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.180         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.180         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.180         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.181         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.181
2025-07-02 06:41:18.181         # search for the pair that matches best without being identical
2025-07-02 06:41:18.181         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.181         # on junk -- unless we have to)
2025-07-02 06:41:18.181         for j in range(blo, bhi):
2025-07-02 06:41:18.181             bj = b[j]
2025-07-02 06:41:18.181             cruncher.set_seq2(bj)
2025-07-02 06:41:18.181             for i in range(alo, ahi):
2025-07-02 06:41:18.181                 ai = a[i]
2025-07-02 06:41:18.181                 if ai == bj:
2025-07-02 06:41:18.181                     if eqi is None:
2025-07-02 06:41:18.181                         eqi, eqj = i, j
2025-07-02 06:41:18.181                     continue
2025-07-02 06:41:18.181                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.181                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.181                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.181                 # compares by a factor of 3.
2025-07-02 06:41:18.181                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.182                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.182                 # of the computation is cached by cruncher
2025-07-02 06:41:18.182                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.182                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.182                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.182                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.182         if best_ratio < cutoff:
2025-07-02 06:41:18.182             # no non-identical "pretty close" pair
2025-07-02 06:41:18.182             if eqi is None:
2025-07-02 06:41:18.182                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.182                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.182                 return
2025-07-02 06:41:18.182             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.182             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.182         else:
2025-07-02 06:41:18.182             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.182             eqi = None
2025-07-02 06:41:18.182
2025-07-02 06:41:18.182         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.182         # identical
2025-07-02 06:41:18.183
2025-07-02 06:41:18.183         # pump out diffs from before the synch point
2025-07-02 06:41:18.183         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.183
2025-07-02 06:41:18.183         # do intraline marking on the synch pair
2025-07-02 06:41:18.183         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.183         if eqi is None:
2025-07-02 06:41:18.183             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.183             atags = btags = ""
2025-07-02 06:41:18.183             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.183             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.183                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.183                 if tag == 'replace':
2025-07-02 06:41:18.183                     atags += '^' * la
2025-07-02 06:41:18.183                     btags += '^' * lb
2025-07-02 06:41:18.183                 elif tag == 'delete':
2025-07-02 06:41:18.183                     atags += '-' * la
2025-07-02 06:41:18.183                 elif tag == 'insert':
2025-07-02 06:41:18.184                     btags += '+' * lb
2025-07-02 06:41:18.184                 elif tag == 'equal':
2025-07-02 06:41:18.184                     atags += ' ' * la
2025-07-02 06:41:18.184                     btags += ' ' * lb
2025-07-02 06:41:18.184                 else:
2025-07-02 06:41:18.184                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.184             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.184         else:
2025-07-02 06:41:18.184             # the synch pair is identical
2025-07-02 06:41:18.184             yield '  ' + aelt
2025-07-02 06:41:18.184
2025-07-02 06:41:18.184         # pump out diffs from after the synch point
2025-07-02 06:41:18.184 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.184
2025-07-02 06:41:18.184 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.184 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.184
2025-07-02 06:41:18.184 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.184 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.184 alo = 358, ahi = 1101
2025-07-02 06:41:18.185 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.185 blo = 358, bhi = 1101
2025-07-02 06:41:18.185
2025-07-02 06:41:18.185     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.185         g = []
2025-07-02 06:41:18.185         if alo < ahi:
2025-07-02 06:41:18.185             if blo < bhi:
2025-07-02 06:41:18.185                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.185             else:
2025-07-02 06:41:18.185                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.185         elif blo < bhi:
2025-07-02 06:41:18.185             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.185
2025-07-02 06:41:18.185 >       yield from g
2025-07-02 06:41:18.185
2025-07-02 06:41:18.185 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.185 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.185
2025-07-02 06:41:18.185 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.185 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.186 alo = 358, ahi = 1101
2025-07-02 06:41:18.186 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.186 blo = 358, bhi = 1101
2025-07-02 06:41:18.186
2025-07-02 06:41:18.186     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.186         r"""
2025-07-02 06:41:18.186         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.186         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.186         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.186         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.186
2025-07-02 06:41:18.186         Example:
2025-07-02 06:41:18.186
2025-07-02 06:41:18.186         >>> d = Differ()
2025-07-02 06:41:18.186         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.186         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.186         >>> print(''.join(results), end="")
2025-07-02 06:41:18.186         - abcDefghiJkl
2025-07-02 06:41:18.186         + abcdefGhijkl
2025-07-02 06:41:18.187         """
2025-07-02 06:41:18.187
2025-07-02 06:41:18.187         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.187         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.187         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.187         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.187         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.187
2025-07-02 06:41:18.187         # search for the pair that matches best without being identical
2025-07-02 06:41:18.187         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.187         # on junk -- unless we have to)
2025-07-02 06:41:18.187         for j in range(blo, bhi):
2025-07-02 06:41:18.187             bj = b[j]
2025-07-02 06:41:18.187             cruncher.set_seq2(bj)
2025-07-02 06:41:18.187             for i in range(alo, ahi):
2025-07-02 06:41:18.187                 ai = a[i]
2025-07-02 06:41:18.187                 if ai == bj:
2025-07-02 06:41:18.187                     if eqi is None:
2025-07-02 06:41:18.187                         eqi, eqj = i, j
2025-07-02 06:41:18.187                     continue
2025-07-02 06:41:18.188                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.188                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.188                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.188                 # compares by a factor of 3.
2025-07-02 06:41:18.188                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.188                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.188                 # of the computation is cached by cruncher
2025-07-02 06:41:18.188                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.188                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.188                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.188                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.188         if best_ratio < cutoff:
2025-07-02 06:41:18.188             # no non-identical "pretty close" pair
2025-07-02 06:41:18.188             if eqi is None:
2025-07-02 06:41:18.188                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.188                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.188                 return
2025-07-02 06:41:18.188             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.189             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.189         else:
2025-07-02 06:41:18.189             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.189             eqi = None
2025-07-02 06:41:18.189
2025-07-02 06:41:18.189         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.189         # identical
2025-07-02 06:41:18.189
2025-07-02 06:41:18.189         # pump out diffs from before the synch point
2025-07-02 06:41:18.189         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.189
2025-07-02 06:41:18.189         # do intraline marking on the synch pair
2025-07-02 06:41:18.189         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.189         if eqi is None:
2025-07-02 06:41:18.189             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.189             atags = btags = ""
2025-07-02 06:41:18.189             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.189             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.189                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.190                 if tag == 'replace':
2025-07-02 06:41:18.190                     atags += '^' * la
2025-07-02 06:41:18.190                     btags += '^' * lb
2025-07-02 06:41:18.190                 elif tag == 'delete':
2025-07-02 06:41:18.190                     atags += '-' * la
2025-07-02 06:41:18.190                 elif tag == 'insert':
2025-07-02 06:41:18.190                     btags += '+' * lb
2025-07-02 06:41:18.190                 elif tag == 'equal':
2025-07-02 06:41:18.190                     atags += ' ' * la
2025-07-02 06:41:18.190                     btags += ' ' * lb
2025-07-02 06:41:18.190                 else:
2025-07-02 06:41:18.190                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.190             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.190         else:
2025-07-02 06:41:18.190             # the synch pair is identical
2025-07-02 06:41:18.190             yield '  ' + aelt
2025-07-02 06:41:18.190
2025-07-02 06:41:18.190         # pump out diffs from after the synch point
2025-07-02 06:41:18.190 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.190
2025-07-02 06:41:18.191 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.191 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.191
2025-07-02 06:41:18.191 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.191 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.191 alo = 359, ahi = 1101
2025-07-02 06:41:18.191 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.191 blo = 359, bhi = 1101
2025-07-02 06:41:18.191
2025-07-02 06:41:18.191     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.191         g = []
2025-07-02 06:41:18.191         if alo < ahi:
2025-07-02 06:41:18.191             if blo < bhi:
2025-07-02 06:41:18.191                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.191             else:
2025-07-02 06:41:18.191                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.191         elif blo < bhi:
2025-07-02 06:41:18.191             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.191
2025-07-02 06:41:18.191 >       yield from g
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.192 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.192 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.192 alo = 359, ahi = 1101
2025-07-02 06:41:18.192 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.192 blo = 359, bhi = 1101
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.192         r"""
2025-07-02 06:41:18.192         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.192         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.192         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.192         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192         Example:
2025-07-02 06:41:18.192
2025-07-02 06:41:18.192         >>> d = Differ()
2025-07-02 06:41:18.192         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.193         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.193         >>> print(''.join(results), end="")
2025-07-02 06:41:18.193         - abcDefghiJkl
2025-07-02 06:41:18.193         + abcdefGhijkl
2025-07-02 06:41:18.193         """
2025-07-02 06:41:18.193
2025-07-02 06:41:18.193         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.193         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.193         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.193         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.193         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.193
2025-07-02 06:41:18.193         # search for the pair that matches best without being identical
2025-07-02 06:41:18.193         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.193         # on junk -- unless we have to)
2025-07-02 06:41:18.193         for j in range(blo, bhi):
2025-07-02 06:41:18.193             bj = b[j]
2025-07-02 06:41:18.193             cruncher.set_seq2(bj)
2025-07-02 06:41:18.194             for i in range(alo, ahi):
2025-07-02 06:41:18.194                 ai = a[i]
2025-07-02 06:41:18.194                 if ai == bj:
2025-07-02 06:41:18.194                     if eqi is None:
2025-07-02 06:41:18.194                         eqi, eqj = i, j
2025-07-02 06:41:18.194                     continue
2025-07-02 06:41:18.194                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.194                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.194                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.194                 # compares by a factor of 3.
2025-07-02 06:41:18.194                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.194                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.194                 # of the computation is cached by cruncher
2025-07-02 06:41:18.194                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.194                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.194                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.194                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.194         if best_ratio < cutoff:
2025-07-02 06:41:18.194             # no non-identical "pretty close" pair
2025-07-02 06:41:18.194             if eqi is None:
2025-07-02 06:41:18.195                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.195                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.195                 return
2025-07-02 06:41:18.195             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.195             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.195         else:
2025-07-02 06:41:18.195             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.195             eqi = None
2025-07-02 06:41:18.195
2025-07-02 06:41:18.195         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.195         # identical
2025-07-02 06:41:18.195
2025-07-02 06:41:18.195         # pump out diffs from before the synch point
2025-07-02 06:41:18.195         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.195
2025-07-02 06:41:18.195         # do intraline marking on the synch pair
2025-07-02 06:41:18.195         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.195         if eqi is None:
2025-07-02 06:41:18.195             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.195             atags = btags = ""
2025-07-02 06:41:18.196             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.196             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.196                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.196                 if tag == 'replace':
2025-07-02 06:41:18.196                     atags += '^' * la
2025-07-02 06:41:18.196                     btags += '^' * lb
2025-07-02 06:41:18.196                 elif tag == 'delete':
2025-07-02 06:41:18.196                     atags += '-' * la
2025-07-02 06:41:18.196                 elif tag == 'insert':
2025-07-02 06:41:18.196                     btags += '+' * lb
2025-07-02 06:41:18.196                 elif tag == 'equal':
2025-07-02 06:41:18.196                     atags += ' ' * la
2025-07-02 06:41:18.196                     btags += ' ' * lb
2025-07-02 06:41:18.196                 else:
2025-07-02 06:41:18.196                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.196             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.196         else:
2025-07-02 06:41:18.196             # the synch pair is identical
2025-07-02 06:41:18.196             yield '  ' + aelt
2025-07-02 06:41:18.196
2025-07-02 06:41:18.196         # pump out diffs from after the synch point
2025-07-02 06:41:18.197 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.197
2025-07-02 06:41:18.197 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.197 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.197
2025-07-02 06:41:18.197 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.197 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.197 alo = 360, ahi = 1101
2025-07-02 06:41:18.197 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.197 blo = 360, bhi = 1101
2025-07-02 06:41:18.197
2025-07-02 06:41:18.197     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.197         g = []
2025-07-02 06:41:18.197         if alo < ahi:
2025-07-02 06:41:18.197             if blo < bhi:
2025-07-02 06:41:18.197                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.197             else:
2025-07-02 06:41:18.197                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.198         elif blo < bhi:
2025-07-02 06:41:18.198             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.198
2025-07-02 06:41:18.198 >       yield from g
2025-07-02 06:41:18.198
2025-07-02 06:41:18.198 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.198 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.198
2025-07-02 06:41:18.198 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.198 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.198 alo = 360, ahi = 1101
2025-07-02 06:41:18.198 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.198 blo = 360, bhi = 1101
2025-07-02 06:41:18.198
2025-07-02 06:41:18.198     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.198         r"""
2025-07-02 06:41:18.198         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.198         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.198         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.199         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.199
2025-07-02 06:41:18.199         Example:
2025-07-02 06:41:18.199
2025-07-02 06:41:18.199         >>> d = Differ()
2025-07-02 06:41:18.199         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.199         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.199         >>> print(''.join(results), end="")
2025-07-02 06:41:18.199         - abcDefghiJkl
2025-07-02 06:41:18.199         + abcdefGhijkl
2025-07-02 06:41:18.199         """
2025-07-02 06:41:18.199
2025-07-02 06:41:18.199         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.199         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.199         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.199         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.199         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.200
2025-07-02 06:41:18.200         # search for the pair that matches best without being identical
2025-07-02 06:41:18.200         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.200         # on junk -- unless we have to)
2025-07-02 06:41:18.200         for j in range(blo, bhi):
2025-07-02 06:41:18.200             bj = b[j]
2025-07-02 06:41:18.200             cruncher.set_seq2(bj)
2025-07-02 06:41:18.200             for i in range(alo, ahi):
2025-07-02 06:41:18.200                 ai = a[i]
2025-07-02 06:41:18.200                 if ai == bj:
2025-07-02 06:41:18.200                     if eqi is None:
2025-07-02 06:41:18.200                         eqi, eqj = i, j
2025-07-02 06:41:18.200                     continue
2025-07-02 06:41:18.200                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.200                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.200                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.200                 # compares by a factor of 3.
2025-07-02 06:41:18.200                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.200                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.200                 # of the computation is cached by cruncher
2025-07-02 06:41:18.201                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.201                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.201                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.201                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.201         if best_ratio < cutoff:
2025-07-02 06:41:18.201             # no non-identical "pretty close" pair
2025-07-02 06:41:18.201             if eqi is None:
2025-07-02 06:41:18.201                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.201                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.201                 return
2025-07-02 06:41:18.201             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.201             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.201         else:
2025-07-02 06:41:18.201             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.201             eqi = None
2025-07-02 06:41:18.201
2025-07-02 06:41:18.201         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.201         # identical
2025-07-02 06:41:18.201
2025-07-02 06:41:18.201         # pump out diffs from before the synch point
2025-07-02 06:41:18.202         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.202
2025-07-02 06:41:18.202         # do intraline marking on the synch pair
2025-07-02 06:41:18.202         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.202         if eqi is None:
2025-07-02 06:41:18.202             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.202             atags = btags = ""
2025-07-02 06:41:18.202             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.202             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.202                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.202                 if tag == 'replace':
2025-07-02 06:41:18.202                     atags += '^' * la
2025-07-02 06:41:18.202                     btags += '^' * lb
2025-07-02 06:41:18.202                 elif tag == 'delete':
2025-07-02 06:41:18.202                     atags += '-' * la
2025-07-02 06:41:18.202                 elif tag == 'insert':
2025-07-02 06:41:18.202                     btags += '+' * lb
2025-07-02 06:41:18.202                 elif tag == 'equal':
2025-07-02 06:41:18.202                     atags += ' ' * la
2025-07-02 06:41:18.202                     btags += ' ' * lb
2025-07-02 06:41:18.203                 else:
2025-07-02 06:41:18.203                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.203             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.203         else:
2025-07-02 06:41:18.203             # the synch pair is identical
2025-07-02 06:41:18.203             yield '  ' + aelt
2025-07-02 06:41:18.203
2025-07-02 06:41:18.203         # pump out diffs from after the synch point
2025-07-02 06:41:18.203 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.203
2025-07-02 06:41:18.203 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.203 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.203
2025-07-02 06:41:18.203 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.203 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.203 alo = 361, ahi = 1101
2025-07-02 06:41:18.203 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.203 blo = 361, bhi = 1101
2025-07-02 06:41:18.203
2025-07-02 06:41:18.203     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.204         g = []
2025-07-02 06:41:18.204         if alo < ahi:
2025-07-02 06:41:18.204             if blo < bhi:
2025-07-02 06:41:18.204                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.204             else:
2025-07-02 06:41:18.204                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.204         elif blo < bhi:
2025-07-02 06:41:18.204             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.204
2025-07-02 06:41:18.204 >       yield from g
2025-07-02 06:41:18.204
2025-07-02 06:41:18.204 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.204 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.204
2025-07-02 06:41:18.204 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.204 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.204 alo = 361, ahi = 1101
2025-07-02 06:41:18.204 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.204 blo = 361, bhi = 1101
2025-07-02 06:41:18.204
2025-07-02 06:41:18.205     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.205         r"""
2025-07-02 06:41:18.205         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.205         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.205         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.205         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.205
2025-07-02 06:41:18.205         Example:
2025-07-02 06:41:18.205
2025-07-02 06:41:18.205         >>> d = Differ()
2025-07-02 06:41:18.205         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.205         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.205         >>> print(''.join(results), end="")
2025-07-02 06:41:18.205         - abcDefghiJkl
2025-07-02 06:41:18.205         + abcdefGhijkl
2025-07-02 06:41:18.205         """
2025-07-02 06:41:18.205
2025-07-02 06:41:18.205         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.205         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.206         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.206         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.206         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.206
2025-07-02 06:41:18.206         # search for the pair that matches best without being identical
2025-07-02 06:41:18.206         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.206         # on junk -- unless we have to)
2025-07-02 06:41:18.206         for j in range(blo, bhi):
2025-07-02 06:41:18.206             bj = b[j]
2025-07-02 06:41:18.206             cruncher.set_seq2(bj)
2025-07-02 06:41:18.206             for i in range(alo, ahi):
2025-07-02 06:41:18.206                 ai = a[i]
2025-07-02 06:41:18.206                 if ai == bj:
2025-07-02 06:41:18.206                     if eqi is None:
2025-07-02 06:41:18.206                         eqi, eqj = i, j
2025-07-02 06:41:18.206                     continue
2025-07-02 06:41:18.206                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.207                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.207                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.207                 # compares by a factor of 3.
2025-07-02 06:41:18.207                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.207                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.207                 # of the computation is cached by cruncher
2025-07-02 06:41:18.207                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.207                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.207                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.207                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.207         if best_ratio < cutoff:
2025-07-02 06:41:18.207             # no non-identical "pretty close" pair
2025-07-02 06:41:18.207             if eqi is None:
2025-07-02 06:41:18.207                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.207                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.207                 return
2025-07-02 06:41:18.207             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.207             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.207         else:
2025-07-02 06:41:18.207             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.208             eqi = None
2025-07-02 06:41:18.208
2025-07-02 06:41:18.208         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.208         # identical
2025-07-02 06:41:18.208
2025-07-02 06:41:18.208         # pump out diffs from before the synch point
2025-07-02 06:41:18.208         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.208
2025-07-02 06:41:18.208         # do intraline marking on the synch pair
2025-07-02 06:41:18.208         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.208         if eqi is None:
2025-07-02 06:41:18.208             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.208             atags = btags = ""
2025-07-02 06:41:18.208             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.208             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.208                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.208                 if tag == 'replace':
2025-07-02 06:41:18.208                     atags += '^' * la
2025-07-02 06:41:18.208                     btags += '^' * lb
2025-07-02 06:41:18.209                 elif tag == 'delete':
2025-07-02 06:41:18.209                     atags += '-' * la
2025-07-02 06:41:18.209                 elif tag == 'insert':
2025-07-02 06:41:18.209                     btags += '+' * lb
2025-07-02 06:41:18.209                 elif tag == 'equal':
2025-07-02 06:41:18.209                     atags += ' ' * la
2025-07-02 06:41:18.209                     btags += ' ' * lb
2025-07-02 06:41:18.209                 else:
2025-07-02 06:41:18.209                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.209             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.209         else:
2025-07-02 06:41:18.209             # the synch pair is identical
2025-07-02 06:41:18.209             yield '  ' + aelt
2025-07-02 06:41:18.209
2025-07-02 06:41:18.209         # pump out diffs from after the synch point
2025-07-02 06:41:18.209 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.209
2025-07-02 06:41:18.209 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.209 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.209
2025-07-02 06:41:18.210 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.210 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.210 alo = 362, ahi = 1101
2025-07-02 06:41:18.210 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.210 blo = 362, bhi = 1101
2025-07-02 06:41:18.210
2025-07-02 06:41:18.210     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.210         g = []
2025-07-02 06:41:18.210         if alo < ahi:
2025-07-02 06:41:18.210             if blo < bhi:
2025-07-02 06:41:18.210                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.210             else:
2025-07-02 06:41:18.210                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.210         elif blo < bhi:
2025-07-02 06:41:18.210             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.210
2025-07-02 06:41:18.210 >       yield from g
2025-07-02 06:41:18.210
2025-07-02 06:41:18.210 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.211 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.211
2025-07-02 06:41:18.211 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.211 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.211 alo = 362, ahi = 1101
2025-07-02 06:41:18.211 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.211 blo = 362, bhi = 1101
2025-07-02 06:41:18.211
2025-07-02 06:41:18.211     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.211         r"""
2025-07-02 06:41:18.211         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.211         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.211         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.211         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.211
2025-07-02 06:41:18.211         Example:
2025-07-02 06:41:18.211
2025-07-02 06:41:18.211         >>> d = Differ()
2025-07-02 06:41:18.211         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.212         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.212         >>> print(''.join(results), end="")
2025-07-02 06:41:18.212         - abcDefghiJkl
2025-07-02 06:41:18.212         + abcdefGhijkl
2025-07-02 06:41:18.212         """
2025-07-02 06:41:18.212
2025-07-02 06:41:18.212         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.212         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.212         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.212         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.212         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.212
2025-07-02 06:41:18.212         # search for the pair that matches best without being identical
2025-07-02 06:41:18.212         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.212         # on junk -- unless we have to)
2025-07-02 06:41:18.212         for j in range(blo, bhi):
2025-07-02 06:41:18.212             bj = b[j]
2025-07-02 06:41:18.212             cruncher.set_seq2(bj)
2025-07-02 06:41:18.213             for i in range(alo, ahi):
2025-07-02 06:41:18.213                 ai = a[i]
2025-07-02 06:41:18.213                 if ai == bj:
2025-07-02 06:41:18.213                     if eqi is None:
2025-07-02 06:41:18.213                         eqi, eqj = i, j
2025-07-02 06:41:18.213                     continue
2025-07-02 06:41:18.213                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.213                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.213                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.213                 # compares by a factor of 3.
2025-07-02 06:41:18.213                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.213                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.213                 # of the computation is cached by cruncher
2025-07-02 06:41:18.213                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.213                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.213                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.213                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.213         if best_ratio < cutoff:
2025-07-02 06:41:18.213             # no non-identical "pretty close" pair
2025-07-02 06:41:18.213             if eqi is None:
2025-07-02 06:41:18.214                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.214                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.214                 return
2025-07-02 06:41:18.214             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.214             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.214         else:
2025-07-02 06:41:18.214             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.214             eqi = None
2025-07-02 06:41:18.214
2025-07-02 06:41:18.214         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.214         # identical
2025-07-02 06:41:18.214
2025-07-02 06:41:18.214         # pump out diffs from before the synch point
2025-07-02 06:41:18.214         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.214
2025-07-02 06:41:18.214         # do intraline marking on the synch pair
2025-07-02 06:41:18.214         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.214         if eqi is None:
2025-07-02 06:41:18.214             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.215             atags = btags = ""
2025-07-02 06:41:18.215             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.215             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.215                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.215                 if tag == 'replace':
2025-07-02 06:41:18.215                     atags += '^' * la
2025-07-02 06:41:18.215                     btags += '^' * lb
2025-07-02 06:41:18.215                 elif tag == 'delete':
2025-07-02 06:41:18.215                     atags += '-' * la
2025-07-02 06:41:18.215                 elif tag == 'insert':
2025-07-02 06:41:18.215                     btags += '+' * lb
2025-07-02 06:41:18.215                 elif tag == 'equal':
2025-07-02 06:41:18.215                     atags += ' ' * la
2025-07-02 06:41:18.215                     btags += ' ' * lb
2025-07-02 06:41:18.215                 else:
2025-07-02 06:41:18.215                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.215             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.216         else:
2025-07-02 06:41:18.216             # the synch pair is identical
2025-07-02 06:41:18.216             yield '  ' + aelt
2025-07-02 06:41:18.216
2025-07-02 06:41:18.216         # pump out diffs from after the synch point
2025-07-02 06:41:18.216 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.216
2025-07-02 06:41:18.216 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.216 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.216
2025-07-02 06:41:18.216 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.216 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.216 alo = 363, ahi = 1101
2025-07-02 06:41:18.216 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.216 blo = 363, bhi = 1101
2025-07-02 06:41:18.216
2025-07-02 06:41:18.216     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.216         g = []
2025-07-02 06:41:18.216         if alo < ahi:
2025-07-02 06:41:18.217             if blo < bhi:
2025-07-02 06:41:18.217                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.217             else:
2025-07-02 06:41:18.217                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.217         elif blo < bhi:
2025-07-02 06:41:18.217             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.217
2025-07-02 06:41:18.217 >       yield from g
2025-07-02 06:41:18.217
2025-07-02 06:41:18.217 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.217 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.217
2025-07-02 06:41:18.217 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.217 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.217 alo = 363, ahi = 1101
2025-07-02 06:41:18.217 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.217 blo = 363, bhi = 1101
2025-07-02 06:41:18.217
2025-07-02 06:41:18.217     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.218         r"""
2025-07-02 06:41:18.218         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.218         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.218         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.218         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.218
2025-07-02 06:41:18.218         Example:
2025-07-02 06:41:18.218
2025-07-02 06:41:18.218         >>> d = Differ()
2025-07-02 06:41:18.218         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.218         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.218         >>> print(''.join(results), end="")
2025-07-02 06:41:18.218         - abcDefghiJkl
2025-07-02 06:41:18.218         + abcdefGhijkl
2025-07-02 06:41:18.218         """
2025-07-02 06:41:18.218
2025-07-02 06:41:18.218         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.218         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.219         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.219         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.219         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.219
2025-07-02 06:41:18.219         # search for the pair that matches best without being identical
2025-07-02 06:41:18.219         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.219         # on junk -- unless we have to)
2025-07-02 06:41:18.219         for j in range(blo, bhi):
2025-07-02 06:41:18.219             bj = b[j]
2025-07-02 06:41:18.219             cruncher.set_seq2(bj)
2025-07-02 06:41:18.219             for i in range(alo, ahi):
2025-07-02 06:41:18.219                 ai = a[i]
2025-07-02 06:41:18.219                 if ai == bj:
2025-07-02 06:41:18.219                     if eqi is None:
2025-07-02 06:41:18.219                         eqi, eqj = i, j
2025-07-02 06:41:18.219                     continue
2025-07-02 06:41:18.219                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.219                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.219                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.220                 # compares by a factor of 3.
2025-07-02 06:41:18.220                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.220                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.220                 # of the computation is cached by cruncher
2025-07-02 06:41:18.220                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.220                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.220                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.220                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.220         if best_ratio < cutoff:
2025-07-02 06:41:18.220             # no non-identical "pretty close" pair
2025-07-02 06:41:18.220             if eqi is None:
2025-07-02 06:41:18.220                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.220                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.220                 return
2025-07-02 06:41:18.220             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.220             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.220         else:
2025-07-02 06:41:18.220             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.220             eqi = None
2025-07-02 06:41:18.221
2025-07-02 06:41:18.221         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.221         # identical
2025-07-02 06:41:18.221
2025-07-02 06:41:18.221         # pump out diffs from before the synch point
2025-07-02 06:41:18.221         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.221
2025-07-02 06:41:18.221         # do intraline marking on the synch pair
2025-07-02 06:41:18.221         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.221         if eqi is None:
2025-07-02 06:41:18.221             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.221             atags = btags = ""
2025-07-02 06:41:18.221             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.221             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.221                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.221                 if tag == 'replace':
2025-07-02 06:41:18.221                     atags += '^' * la
2025-07-02 06:41:18.221                     btags += '^' * lb
2025-07-02 06:41:18.221                 elif tag == 'delete':
2025-07-02 06:41:18.221                     atags += '-' * la
2025-07-02 06:41:18.222                 elif tag == 'insert':
2025-07-02 06:41:18.222                     btags += '+' * lb
2025-07-02 06:41:18.222                 elif tag == 'equal':
2025-07-02 06:41:18.222                     atags += ' ' * la
2025-07-02 06:41:18.222                     btags += ' ' * lb
2025-07-02 06:41:18.222                 else:
2025-07-02 06:41:18.222                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.222             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.222         else:
2025-07-02 06:41:18.222             # the synch pair is identical
2025-07-02 06:41:18.222             yield '  ' + aelt
2025-07-02 06:41:18.222
2025-07-02 06:41:18.222         # pump out diffs from after the synch point
2025-07-02 06:41:18.222 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.222
2025-07-02 06:41:18.222 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.222 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.222
2025-07-02 06:41:18.222 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.223 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.223 alo = 364, ahi = 1101
2025-07-02 06:41:18.223 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.223 blo = 364, bhi = 1101
2025-07-02 06:41:18.223
2025-07-02 06:41:18.223     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.223         g = []
2025-07-02 06:41:18.223         if alo < ahi:
2025-07-02 06:41:18.223             if blo < bhi:
2025-07-02 06:41:18.223                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.223             else:
2025-07-02 06:41:18.223                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.223         elif blo < bhi:
2025-07-02 06:41:18.223             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.223
2025-07-02 06:41:18.223 >       yield from g
2025-07-02 06:41:18.223
2025-07-02 06:41:18.223 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.224 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.224
2025-07-02 06:41:18.224 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.224 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.224 alo = 364, ahi = 1101
2025-07-02 06:41:18.224 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.224 blo = 364, bhi = 1101
2025-07-02 06:41:18.224
2025-07-02 06:41:18.224     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.224         r"""
2025-07-02 06:41:18.224         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.224         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.224         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.224         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.224
2025-07-02 06:41:18.224         Example:
2025-07-02 06:41:18.224
2025-07-02 06:41:18.224         >>> d = Differ()
2025-07-02 06:41:18.224         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.225         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.225         >>> print(''.join(results), end="")
2025-07-02 06:41:18.225         - abcDefghiJkl
2025-07-02 06:41:18.225         + abcdefGhijkl
2025-07-02 06:41:18.225         """
2025-07-02 06:41:18.225
2025-07-02 06:41:18.225         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.225         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.225         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.225         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.225         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.225
2025-07-02 06:41:18.225         # search for the pair that matches best without being identical
2025-07-02 06:41:18.225         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.225         # on junk -- unless we have to)
2025-07-02 06:41:18.225         for j in range(blo, bhi):
2025-07-02 06:41:18.225             bj = b[j]
2025-07-02 06:41:18.225             cruncher.set_seq2(bj)
2025-07-02 06:41:18.226             for i in range(alo, ahi):
2025-07-02 06:41:18.226                 ai = a[i]
2025-07-02 06:41:18.226                 if ai == bj:
2025-07-02 06:41:18.226                     if eqi is None:
2025-07-02 06:41:18.226                         eqi, eqj = i, j
2025-07-02 06:41:18.226                     continue
2025-07-02 06:41:18.226                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.226                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.226                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.226                 # compares by a factor of 3.
2025-07-02 06:41:18.226                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.226                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.226                 # of the computation is cached by cruncher
2025-07-02 06:41:18.226                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.226                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.226                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.226                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.226         if best_ratio < cutoff:
2025-07-02 06:41:18.226             # no non-identical "pretty close" pair
2025-07-02 06:41:18.227             if eqi is None:
2025-07-02 06:41:18.227                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.227                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.227                 return
2025-07-02 06:41:18.227             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.227             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.227         else:
2025-07-02 06:41:18.227             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.227             eqi = None
2025-07-02 06:41:18.227
2025-07-02 06:41:18.227         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.227         # identical
2025-07-02 06:41:18.227
2025-07-02 06:41:18.227         # pump out diffs from before the synch point
2025-07-02 06:41:18.227         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.227
2025-07-02 06:41:18.227         # do intraline marking on the synch pair
2025-07-02 06:41:18.227         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.227         if eqi is None:
2025-07-02 06:41:18.227             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.228             atags = btags = ""
2025-07-02 06:41:18.228             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.228             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.228                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.228                 if tag == 'replace':
2025-07-02 06:41:18.228                     atags += '^' * la
2025-07-02 06:41:18.228                     btags += '^' * lb
2025-07-02 06:41:18.228                 elif tag == 'delete':
2025-07-02 06:41:18.228                     atags += '-' * la
2025-07-02 06:41:18.228                 elif tag == 'insert':
2025-07-02 06:41:18.228                     btags += '+' * lb
2025-07-02 06:41:18.228                 elif tag == 'equal':
2025-07-02 06:41:18.228                     atags += ' ' * la
2025-07-02 06:41:18.228                     btags += ' ' * lb
2025-07-02 06:41:18.228                 else:
2025-07-02 06:41:18.228                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.228             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.228         else:
2025-07-02 06:41:18.228             # the synch pair is identical
2025-07-02 06:41:18.229             yield '  ' + aelt
2025-07-02 06:41:18.229
2025-07-02 06:41:18.229         # pump out diffs from after the synch point
2025-07-02 06:41:18.229 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.229
2025-07-02 06:41:18.229 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.229 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.229
2025-07-02 06:41:18.229 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.229 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.229 alo = 365, ahi = 1101
2025-07-02 06:41:18.229 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.229 blo = 365, bhi = 1101
2025-07-02 06:41:18.229
2025-07-02 06:41:18.229     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.229         g = []
2025-07-02 06:41:18.229         if alo < ahi:
2025-07-02 06:41:18.229             if blo < bhi:
2025-07-02 06:41:18.229                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.230             else:
2025-07-02 06:41:18.230                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.230         elif blo < bhi:
2025-07-02 06:41:18.230             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.230
2025-07-02 06:41:18.230 >       yield from g
2025-07-02 06:41:18.230
2025-07-02 06:41:18.230 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.230 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.230
2025-07-02 06:41:18.230 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.230 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.230 alo = 365, ahi = 1101
2025-07-02 06:41:18.230 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.230 blo = 365, bhi = 1101
2025-07-02 06:41:18.230
2025-07-02 06:41:18.230     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.230         r"""
2025-07-02 06:41:18.230         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.231         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.231         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.231         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.231
2025-07-02 06:41:18.231         Example:
2025-07-02 06:41:18.231
2025-07-02 06:41:18.231         >>> d = Differ()
2025-07-02 06:41:18.231         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.231         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.231         >>> print(''.join(results), end="")
2025-07-02 06:41:18.231         - abcDefghiJkl
2025-07-02 06:41:18.231         + abcdefGhijkl
2025-07-02 06:41:18.231         """
2025-07-02 06:41:18.231
2025-07-02 06:41:18.231         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.231         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.231         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.231         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.232         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.232
2025-07-02 06:41:18.232         # search for the pair that matches best without being identical
2025-07-02 06:41:18.232         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.232         # on junk -- unless we have to)
2025-07-02 06:41:18.232         for j in range(blo, bhi):
2025-07-02 06:41:18.232             bj = b[j]
2025-07-02 06:41:18.232             cruncher.set_seq2(bj)
2025-07-02 06:41:18.232             for i in range(alo, ahi):
2025-07-02 06:41:18.232                 ai = a[i]
2025-07-02 06:41:18.232                 if ai == bj:
2025-07-02 06:41:18.232                     if eqi is None:
2025-07-02 06:41:18.232                         eqi, eqj = i, j
2025-07-02 06:41:18.232                     continue
2025-07-02 06:41:18.232                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.232                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.232                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.232                 # compares by a factor of 3.
2025-07-02 06:41:18.232                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.233                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.233                 # of the computation is cached by cruncher
2025-07-02 06:41:18.233                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.233                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.233                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.233                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.233         if best_ratio < cutoff:
2025-07-02 06:41:18.233             # no non-identical "pretty close" pair
2025-07-02 06:41:18.233             if eqi is None:
2025-07-02 06:41:18.233                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.233                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.233                 return
2025-07-02 06:41:18.233             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.233             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.233         else:
2025-07-02 06:41:18.233             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.233             eqi = None
2025-07-02 06:41:18.233
2025-07-02 06:41:18.234         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.234         # identical
2025-07-02 06:41:18.234
2025-07-02 06:41:18.234         # pump out diffs from before the synch point
2025-07-02 06:41:18.234         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.234
2025-07-02 06:41:18.234         # do intraline marking on the synch pair
2025-07-02 06:41:18.234         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.234         if eqi is None:
2025-07-02 06:41:18.234             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.234             atags = btags = ""
2025-07-02 06:41:18.234             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.234             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.234                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.234                 if tag == 'replace':
2025-07-02 06:41:18.234                     atags += '^' * la
2025-07-02 06:41:18.234                     btags += '^' * lb
2025-07-02 06:41:18.234                 elif tag == 'delete':
2025-07-02 06:41:18.234                     atags += '-' * la
2025-07-02 06:41:18.234                 elif tag == 'insert':
2025-07-02 06:41:18.235                     btags += '+' * lb
2025-07-02 06:41:18.235                 elif tag == 'equal':
2025-07-02 06:41:18.235                     atags += ' ' * la
2025-07-02 06:41:18.235                     btags += ' ' * lb
2025-07-02 06:41:18.235                 else:
2025-07-02 06:41:18.235                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.235             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.235         else:
2025-07-02 06:41:18.235             # the synch pair is identical
2025-07-02 06:41:18.235             yield '  ' + aelt
2025-07-02 06:41:18.235
2025-07-02 06:41:18.235         # pump out diffs from after the synch point
2025-07-02 06:41:18.235 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.235
2025-07-02 06:41:18.235 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.235 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.235
2025-07-02 06:41:18.235 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.235 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.236 alo = 366, ahi = 1101
2025-07-02 06:41:18.236 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.236 blo = 366, bhi = 1101
2025-07-02 06:41:18.236
2025-07-02 06:41:18.236     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.236         g = []
2025-07-02 06:41:18.236         if alo < ahi:
2025-07-02 06:41:18.236             if blo < bhi:
2025-07-02 06:41:18.236                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.236             else:
2025-07-02 06:41:18.236                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.236         elif blo < bhi:
2025-07-02 06:41:18.236             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.236
2025-07-02 06:41:18.236 >       yield from g
2025-07-02 06:41:18.236
2025-07-02 06:41:18.236 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.236 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.236
2025-07-02 06:41:18.237 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.237 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.237 alo = 366, ahi = 1101
2025-07-02 06:41:18.237 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.237 blo = 366, bhi = 1101
2025-07-02 06:41:18.237
2025-07-02 06:41:18.237     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.237         r"""
2025-07-02 06:41:18.237         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.237         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.237         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.237         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.237
2025-07-02 06:41:18.237         Example:
2025-07-02 06:41:18.237
2025-07-02 06:41:18.237         >>> d = Differ()
2025-07-02 06:41:18.237         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.237         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.237         >>> print(''.join(results), end="")
2025-07-02 06:41:18.237         - abcDefghiJkl
2025-07-02 06:41:18.238         + abcdefGhijkl
2025-07-02 06:41:18.238         """
2025-07-02 06:41:18.238
2025-07-02 06:41:18.238         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.238         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.238         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.238         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.238         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.238
2025-07-02 06:41:18.238         # search for the pair that matches best without being identical
2025-07-02 06:41:18.238         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.238         # on junk -- unless we have to)
2025-07-02 06:41:18.238         for j in range(blo, bhi):
2025-07-02 06:41:18.238             bj = b[j]
2025-07-02 06:41:18.238             cruncher.set_seq2(bj)
2025-07-02 06:41:18.238             for i in range(alo, ahi):
2025-07-02 06:41:18.238                 ai = a[i]
2025-07-02 06:41:18.238                 if ai == bj:
2025-07-02 06:41:18.238                     if eqi is None:
2025-07-02 06:41:18.239                         eqi, eqj = i, j
2025-07-02 06:41:18.239                     continue
2025-07-02 06:41:18.239                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.239                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.239                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.239                 # compares by a factor of 3.
2025-07-02 06:41:18.239                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.239                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.239                 # of the computation is cached by cruncher
2025-07-02 06:41:18.239                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.239                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.239                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.239                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.239         if best_ratio < cutoff:
2025-07-02 06:41:18.239             # no non-identical "pretty close" pair
2025-07-02 06:41:18.239             if eqi is None:
2025-07-02 06:41:18.239                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.239                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.239                 return
2025-07-02 06:41:18.239             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.240             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.240         else:
2025-07-02 06:41:18.240             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.240             eqi = None
2025-07-02 06:41:18.240
2025-07-02 06:41:18.240         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.240         # identical
2025-07-02 06:41:18.240
2025-07-02 06:41:18.240         # pump out diffs from before the synch point
2025-07-02 06:41:18.240         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.240
2025-07-02 06:41:18.240         # do intraline marking on the synch pair
2025-07-02 06:41:18.240         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.240         if eqi is None:
2025-07-02 06:41:18.240             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.240             atags = btags = ""
2025-07-02 06:41:18.240             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.240             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.240                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.240                 if tag == 'replace':
2025-07-02 06:41:18.241                     atags += '^' * la
2025-07-02 06:41:18.241                     btags += '^' * lb
2025-07-02 06:41:18.241                 elif tag == 'delete':
2025-07-02 06:41:18.241                     atags += '-' * la
2025-07-02 06:41:18.241                 elif tag == 'insert':
2025-07-02 06:41:18.241                     btags += '+' * lb
2025-07-02 06:41:18.241                 elif tag == 'equal':
2025-07-02 06:41:18.241                     atags += ' ' * la
2025-07-02 06:41:18.241                     btags += ' ' * lb
2025-07-02 06:41:18.241                 else:
2025-07-02 06:41:18.241                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.241             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.241         else:
2025-07-02 06:41:18.241             # the synch pair is identical
2025-07-02 06:41:18.241             yield '  ' + aelt
2025-07-02 06:41:18.241
2025-07-02 06:41:18.241         # pump out diffs from after the synch point
2025-07-02 06:41:18.241 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.241
2025-07-02 06:41:18.242 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.242 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.242
2025-07-02 06:41:18.242 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.242 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.242 alo = 367, ahi = 1101
2025-07-02 06:41:18.242 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.242 blo = 367, bhi = 1101
2025-07-02 06:41:18.242
2025-07-02 06:41:18.242     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.242         g = []
2025-07-02 06:41:18.242         if alo < ahi:
2025-07-02 06:41:18.242             if blo < bhi:
2025-07-02 06:41:18.242                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.242             else:
2025-07-02 06:41:18.242                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.242         elif blo < bhi:
2025-07-02 06:41:18.242             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.242
2025-07-02 06:41:18.243 >       yield from g
2025-07-02 06:41:18.243
2025-07-02 06:41:18.243 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.243 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.243
2025-07-02 06:41:18.243 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.243 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.243 alo = 367, ahi = 1101
2025-07-02 06:41:18.243 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.243 blo = 367, bhi = 1101
2025-07-02 06:41:18.243
2025-07-02 06:41:18.243     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.243         r"""
2025-07-02 06:41:18.243         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.243         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.243         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.243         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.243
2025-07-02 06:41:18.243         Example:
2025-07-02 06:41:18.244
2025-07-02 06:41:18.244         >>> d = Differ()
2025-07-02 06:41:18.244         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.244         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.244         >>> print(''.join(results), end="")
2025-07-02 06:41:18.244         - abcDefghiJkl
2025-07-02 06:41:18.244         + abcdefGhijkl
2025-07-02 06:41:18.244         """
2025-07-02 06:41:18.244
2025-07-02 06:41:18.244         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.244         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.244         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.244         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.244         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.244
2025-07-02 06:41:18.244         # search for the pair that matches best without being identical
2025-07-02 06:41:18.244         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.244         # on junk -- unless we have to)
2025-07-02 06:41:18.245         for j in range(blo, bhi):
2025-07-02 06:41:18.245             bj = b[j]
2025-07-02 06:41:18.245             cruncher.set_seq2(bj)
2025-07-02 06:41:18.245             for i in range(alo, ahi):
2025-07-02 06:41:18.245                 ai = a[i]
2025-07-02 06:41:18.245                 if ai == bj:
2025-07-02 06:41:18.245                     if eqi is None:
2025-07-02 06:41:18.245                         eqi, eqj = i, j
2025-07-02 06:41:18.245                     continue
2025-07-02 06:41:18.245                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.245                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.245                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.245                 # compares by a factor of 3.
2025-07-02 06:41:18.245                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.245                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.245                 # of the computation is cached by cruncher
2025-07-02 06:41:18.245                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.245                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.245                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.246                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.246         if best_ratio < cutoff:
2025-07-02 06:41:18.246             # no non-identical "pretty close" pair
2025-07-02 06:41:18.246             if eqi is None:
2025-07-02 06:41:18.246                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.246                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.246                 return
2025-07-02 06:41:18.246             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.246             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.246         else:
2025-07-02 06:41:18.246             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.246             eqi = None
2025-07-02 06:41:18.246
2025-07-02 06:41:18.246         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.246         # identical
2025-07-02 06:41:18.246
2025-07-02 06:41:18.246         # pump out diffs from before the synch point
2025-07-02 06:41:18.246         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.246
2025-07-02 06:41:18.246         # do intraline marking on the synch pair
2025-07-02 06:41:18.247         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.247         if eqi is None:
2025-07-02 06:41:18.247             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.247             atags = btags = ""
2025-07-02 06:41:18.247             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.247             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.247                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.247                 if tag == 'replace':
2025-07-02 06:41:18.247                     atags += '^' * la
2025-07-02 06:41:18.247                     btags += '^' * lb
2025-07-02 06:41:18.247                 elif tag == 'delete':
2025-07-02 06:41:18.247                     atags += '-' * la
2025-07-02 06:41:18.247                 elif tag == 'insert':
2025-07-02 06:41:18.247                     btags += '+' * lb
2025-07-02 06:41:18.247                 elif tag == 'equal':
2025-07-02 06:41:18.247                     atags += ' ' * la
2025-07-02 06:41:18.247                     btags += ' ' * lb
2025-07-02 06:41:18.247                 else:
2025-07-02 06:41:18.248                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.248             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.248         else:
2025-07-02 06:41:18.248             # the synch pair is identical
2025-07-02 06:41:18.248             yield '  ' + aelt
2025-07-02 06:41:18.248
2025-07-02 06:41:18.248         # pump out diffs from after the synch point
2025-07-02 06:41:18.248 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.248
2025-07-02 06:41:18.248 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.248 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.248
2025-07-02 06:41:18.248 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.248 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.248 alo = 368, ahi = 1101
2025-07-02 06:41:18.248 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.248 blo = 368, bhi = 1101
2025-07-02 06:41:18.248
2025-07-02 06:41:18.248     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.249         g = []
2025-07-02 06:41:18.249         if alo < ahi:
2025-07-02 06:41:18.249             if blo < bhi:
2025-07-02 06:41:18.249                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.249             else:
2025-07-02 06:41:18.249                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.249         elif blo < bhi:
2025-07-02 06:41:18.249             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.249
2025-07-02 06:41:18.249 >       yield from g
2025-07-02 06:41:18.249
2025-07-02 06:41:18.249 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.249 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.249
2025-07-02 06:41:18.249 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.249 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.249 alo = 368, ahi = 1101
2025-07-02 06:41:18.249 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.249 blo = 368, bhi = 1101
2025-07-02 06:41:18.249
2025-07-02 06:41:18.250     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.250         r"""
2025-07-02 06:41:18.250         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.250         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.250         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.250         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.250
2025-07-02 06:41:18.250         Example:
2025-07-02 06:41:18.250
2025-07-02 06:41:18.250         >>> d = Differ()
2025-07-02 06:41:18.250         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.250         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.250         >>> print(''.join(results), end="")
2025-07-02 06:41:18.250         - abcDefghiJkl
2025-07-02 06:41:18.250         + abcdefGhijkl
2025-07-02 06:41:18.250         """
2025-07-02 06:41:18.250
2025-07-02 06:41:18.251         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.251         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.251         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.251         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.251         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.251
2025-07-02 06:41:18.251         # search for the pair that matches best without being identical
2025-07-02 06:41:18.251         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.251         # on junk -- unless we have to)
2025-07-02 06:41:18.251         for j in range(blo, bhi):
2025-07-02 06:41:18.251             bj = b[j]
2025-07-02 06:41:18.251             cruncher.set_seq2(bj)
2025-07-02 06:41:18.251             for i in range(alo, ahi):
2025-07-02 06:41:18.251                 ai = a[i]
2025-07-02 06:41:18.251                 if ai == bj:
2025-07-02 06:41:18.251                     if eqi is None:
2025-07-02 06:41:18.251                         eqi, eqj = i, j
2025-07-02 06:41:18.251                     continue
2025-07-02 06:41:18.251                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.251                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.252                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.252                 # compares by a factor of 3.
2025-07-02 06:41:18.252                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.252                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.252                 # of the computation is cached by cruncher
2025-07-02 06:41:18.252                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.252                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.252                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.252                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.252         if best_ratio < cutoff:
2025-07-02 06:41:18.252             # no non-identical "pretty close" pair
2025-07-02 06:41:18.252             if eqi is None:
2025-07-02 06:41:18.252                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.252                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.252                 return
2025-07-02 06:41:18.252             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.252             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.252         else:
2025-07-02 06:41:18.252             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.253             eqi = None
2025-07-02 06:41:18.253
2025-07-02 06:41:18.253         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.253         # identical
2025-07-02 06:41:18.253
2025-07-02 06:41:18.253         # pump out diffs from before the synch point
2025-07-02 06:41:18.253         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.253
2025-07-02 06:41:18.253         # do intraline marking on the synch pair
2025-07-02 06:41:18.253         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.253         if eqi is None:
2025-07-02 06:41:18.253             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.253             atags = btags = ""
2025-07-02 06:41:18.253             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.253             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.253                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.253                 if tag == 'replace':
2025-07-02 06:41:18.253                     atags += '^' * la
2025-07-02 06:41:18.253                     btags += '^' * lb
2025-07-02 06:41:18.253                 elif tag == 'delete':
2025-07-02 06:41:18.254                     atags += '-' * la
2025-07-02 06:41:18.254                 elif tag == 'insert':
2025-07-02 06:41:18.254                     btags += '+' * lb
2025-07-02 06:41:18.254                 elif tag == 'equal':
2025-07-02 06:41:18.254                     atags += ' ' * la
2025-07-02 06:41:18.254                     btags += ' ' * lb
2025-07-02 06:41:18.254                 else:
2025-07-02 06:41:18.254                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.254             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.254         else:
2025-07-02 06:41:18.254             # the synch pair is identical
2025-07-02 06:41:18.254             yield '  ' + aelt
2025-07-02 06:41:18.254
2025-07-02 06:41:18.254         # pump out diffs from after the synch point
2025-07-02 06:41:18.254 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.254
2025-07-02 06:41:18.254 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.254 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.254
2025-07-02 06:41:18.255 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.255 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.255 alo = 369, ahi = 1101
2025-07-02 06:41:18.255 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.255 blo = 369, bhi = 1101
2025-07-02 06:41:18.255
2025-07-02 06:41:18.255     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.255         g = []
2025-07-02 06:41:18.255         if alo < ahi:
2025-07-02 06:41:18.255             if blo < bhi:
2025-07-02 06:41:18.255                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.255             else:
2025-07-02 06:41:18.255                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.255         elif blo < bhi:
2025-07-02 06:41:18.255             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.255
2025-07-02 06:41:18.255 >       yield from g
2025-07-02 06:41:18.255
2025-07-02 06:41:18.255 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.255 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.256
2025-07-02 06:41:18.256 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.256 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.256 alo = 369, ahi = 1101
2025-07-02 06:41:18.256 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.256 blo = 369, bhi = 1101
2025-07-02 06:41:18.256
2025-07-02 06:41:18.256     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.256         r"""
2025-07-02 06:41:18.256         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.256         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.256         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.256         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.256
2025-07-02 06:41:18.256         Example:
2025-07-02 06:41:18.256
2025-07-02 06:41:18.256         >>> d = Differ()
2025-07-02 06:41:18.256         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.256         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.257         >>> print(''.join(results), end="")
2025-07-02 06:41:18.257         - abcDefghiJkl
2025-07-02 06:41:18.257         + abcdefGhijkl
2025-07-02 06:41:18.257         """
2025-07-02 06:41:18.257
2025-07-02 06:41:18.257         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.257         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.257         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.257         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.257         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.257
2025-07-02 06:41:18.257         # search for the pair that matches best without being identical
2025-07-02 06:41:18.257         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.257         # on junk -- unless we have to)
2025-07-02 06:41:18.257         for j in range(blo, bhi):
2025-07-02 06:41:18.257             bj = b[j]
2025-07-02 06:41:18.257             cruncher.set_seq2(bj)
2025-07-02 06:41:18.257             for i in range(alo, ahi):
2025-07-02 06:41:18.258                 ai = a[i]
2025-07-02 06:41:18.258                 if ai == bj:
2025-07-02 06:41:18.258                     if eqi is None:
2025-07-02 06:41:18.258                         eqi, eqj = i, j
2025-07-02 06:41:18.258                     continue
2025-07-02 06:41:18.258                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.258                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.258                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.258                 # compares by a factor of 3.
2025-07-02 06:41:18.258                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.258                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.258                 # of the computation is cached by cruncher
2025-07-02 06:41:18.258                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.258                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.258                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.258                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.258         if best_ratio < cutoff:
2025-07-02 06:41:18.258             # no non-identical "pretty close" pair
2025-07-02 06:41:18.258             if eqi is None:
2025-07-02 06:41:18.259                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.259                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.259                 return
2025-07-02 06:41:18.259             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.259             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.259         else:
2025-07-02 06:41:18.259             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.259             eqi = None
2025-07-02 06:41:18.259
2025-07-02 06:41:18.259         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.259         # identical
2025-07-02 06:41:18.259
2025-07-02 06:41:18.259         # pump out diffs from before the synch point
2025-07-02 06:41:18.259         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.259
2025-07-02 06:41:18.259         # do intraline marking on the synch pair
2025-07-02 06:41:18.259         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.259         if eqi is None:
2025-07-02 06:41:18.259             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.260             atags = btags = ""
2025-07-02 06:41:18.260             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.260             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.260                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.260                 if tag == 'replace':
2025-07-02 06:41:18.260                     atags += '^' * la
2025-07-02 06:41:18.260                     btags += '^' * lb
2025-07-02 06:41:18.260                 elif tag == 'delete':
2025-07-02 06:41:18.260                     atags += '-' * la
2025-07-02 06:41:18.260                 elif tag == 'insert':
2025-07-02 06:41:18.260                     btags += '+' * lb
2025-07-02 06:41:18.260                 elif tag == 'equal':
2025-07-02 06:41:18.260                     atags += ' ' * la
2025-07-02 06:41:18.260                     btags += ' ' * lb
2025-07-02 06:41:18.260                 else:
2025-07-02 06:41:18.260                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.260             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.260         else:
2025-07-02 06:41:18.260             # the synch pair is identical
2025-07-02 06:41:18.260             yield '  ' + aelt
2025-07-02 06:41:18.261
2025-07-02 06:41:18.261         # pump out diffs from after the synch point
2025-07-02 06:41:18.261 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.261
2025-07-02 06:41:18.261 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.261 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.261
2025-07-02 06:41:18.261 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.261 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.261 alo = 370, ahi = 1101
2025-07-02 06:41:18.261 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.261 blo = 370, bhi = 1101
2025-07-02 06:41:18.261
2025-07-02 06:41:18.261     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.261         g = []
2025-07-02 06:41:18.261         if alo < ahi:
2025-07-02 06:41:18.261             if blo < bhi:
2025-07-02 06:41:18.261                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.261             else:
2025-07-02 06:41:18.262                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.262         elif blo < bhi:
2025-07-02 06:41:18.262             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.262
2025-07-02 06:41:18.262 >       yield from g
2025-07-02 06:41:18.262
2025-07-02 06:41:18.262 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.262 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.262
2025-07-02 06:41:18.262 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.262 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.262 alo = 370, ahi = 1101
2025-07-02 06:41:18.262 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.262 blo = 370, bhi = 1101
2025-07-02 06:41:18.262
2025-07-02 06:41:18.262     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.262         r"""
2025-07-02 06:41:18.262         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.262         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.263         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.263         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.263
2025-07-02 06:41:18.263         Example:
2025-07-02 06:41:18.263
2025-07-02 06:41:18.263         >>> d = Differ()
2025-07-02 06:41:18.263         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.263         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.263         >>> print(''.join(results), end="")
2025-07-02 06:41:18.263         - abcDefghiJkl
2025-07-02 06:41:18.263         + abcdefGhijkl
2025-07-02 06:41:18.263         """
2025-07-02 06:41:18.263
2025-07-02 06:41:18.263         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.263         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.263         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.263         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.264         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.264
2025-07-02 06:41:18.264         # search for the pair that matches best without being identical
2025-07-02 06:41:18.264         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.264         # on junk -- unless we have to)
2025-07-02 06:41:18.264         for j in range(blo, bhi):
2025-07-02 06:41:18.264             bj = b[j]
2025-07-02 06:41:18.264             cruncher.set_seq2(bj)
2025-07-02 06:41:18.264             for i in range(alo, ahi):
2025-07-02 06:41:18.264                 ai = a[i]
2025-07-02 06:41:18.264                 if ai == bj:
2025-07-02 06:41:18.264                     if eqi is None:
2025-07-02 06:41:18.264                         eqi, eqj = i, j
2025-07-02 06:41:18.264                     continue
2025-07-02 06:41:18.264                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.264                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.264                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.264                 # compares by a factor of 3.
2025-07-02 06:41:18.264                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.265                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.265                 # of the computation is cached by cruncher
2025-07-02 06:41:18.265                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.265                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.265                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.265                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.265         if best_ratio < cutoff:
2025-07-02 06:41:18.265             # no non-identical "pretty close" pair
2025-07-02 06:41:18.265             if eqi is None:
2025-07-02 06:41:18.265                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.265                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.265                 return
2025-07-02 06:41:18.265             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.265             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.265         else:
2025-07-02 06:41:18.265             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.265             eqi = None
2025-07-02 06:41:18.265
2025-07-02 06:41:18.265         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.265         # identical
2025-07-02 06:41:18.266
2025-07-02 06:41:18.266         # pump out diffs from before the synch point
2025-07-02 06:41:18.266         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.266
2025-07-02 06:41:18.266         # do intraline marking on the synch pair
2025-07-02 06:41:18.266         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.266         if eqi is None:
2025-07-02 06:41:18.266             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.266             atags = btags = ""
2025-07-02 06:41:18.266             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.266             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.266                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.266                 if tag == 'replace':
2025-07-02 06:41:18.266                     atags += '^' * la
2025-07-02 06:41:18.266                     btags += '^' * lb
2025-07-02 06:41:18.266                 elif tag == 'delete':
2025-07-02 06:41:18.266                     atags += '-' * la
2025-07-02 06:41:18.266                 elif tag == 'insert':
2025-07-02 06:41:18.266                     btags += '+' * lb
2025-07-02 06:41:18.267                 elif tag == 'equal':
2025-07-02 06:41:18.267                     atags += ' ' * la
2025-07-02 06:41:18.267                     btags += ' ' * lb
2025-07-02 06:41:18.267                 else:
2025-07-02 06:41:18.267                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.267             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.267         else:
2025-07-02 06:41:18.267             # the synch pair is identical
2025-07-02 06:41:18.267             yield '  ' + aelt
2025-07-02 06:41:18.267
2025-07-02 06:41:18.267         # pump out diffs from after the synch point
2025-07-02 06:41:18.267 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.267
2025-07-02 06:41:18.267 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.267 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.267
2025-07-02 06:41:18.267 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.267 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.267 alo = 371, ahi = 1101
2025-07-02 06:41:18.267 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.268 blo = 371, bhi = 1101
2025-07-02 06:41:18.268
2025-07-02 06:41:18.268     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.268         g = []
2025-07-02 06:41:18.268         if alo < ahi:
2025-07-02 06:41:18.268             if blo < bhi:
2025-07-02 06:41:18.268                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.268             else:
2025-07-02 06:41:18.268                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.268         elif blo < bhi:
2025-07-02 06:41:18.268             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.268
2025-07-02 06:41:18.268 >       yield from g
2025-07-02 06:41:18.268
2025-07-02 06:41:18.268 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.268 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.268
2025-07-02 06:41:18.268 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.269 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.269 alo = 371, ahi = 1101
2025-07-02 06:41:18.269 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.269 blo = 371, bhi = 1101
2025-07-02 06:41:18.269
2025-07-02 06:41:18.269     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.269         r"""
2025-07-02 06:41:18.269         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.269         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.269         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.269         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.269
2025-07-02 06:41:18.269         Example:
2025-07-02 06:41:18.269
2025-07-02 06:41:18.269         >>> d = Differ()
2025-07-02 06:41:18.269         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.269         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.269         >>> print(''.join(results), end="")
2025-07-02 06:41:18.269         - abcDefghiJkl
2025-07-02 06:41:18.270         + abcdefGhijkl
2025-07-02 06:41:18.270         """
2025-07-02 06:41:18.270
2025-07-02 06:41:18.270         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.270         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.270         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.270         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.270         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.270
2025-07-02 06:41:18.270         # search for the pair that matches best without being identical
2025-07-02 06:41:18.270         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.270         # on junk -- unless we have to)
2025-07-02 06:41:18.270         for j in range(blo, bhi):
2025-07-02 06:41:18.270             bj = b[j]
2025-07-02 06:41:18.270             cruncher.set_seq2(bj)
2025-07-02 06:41:18.270             for i in range(alo, ahi):
2025-07-02 06:41:18.270                 ai = a[i]
2025-07-02 06:41:18.270                 if ai == bj:
2025-07-02 06:41:18.271                     if eqi is None:
2025-07-02 06:41:18.271                         eqi, eqj = i, j
2025-07-02 06:41:18.271                     continue
2025-07-02 06:41:18.271                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.271                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.271                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.271                 # compares by a factor of 3.
2025-07-02 06:41:18.271                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.271                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.271                 # of the computation is cached by cruncher
2025-07-02 06:41:18.271                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.271                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.271                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.271                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.271         if best_ratio < cutoff:
2025-07-02 06:41:18.271             # no non-identical "pretty close" pair
2025-07-02 06:41:18.271             if eqi is None:
2025-07-02 06:41:18.271                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.272                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.272                 return
2025-07-02 06:41:18.272             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.272             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.272         else:
2025-07-02 06:41:18.272             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.272             eqi = None
2025-07-02 06:41:18.272
2025-07-02 06:41:18.272         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.272         # identical
2025-07-02 06:41:18.272
2025-07-02 06:41:18.272         # pump out diffs from before the synch point
2025-07-02 06:41:18.272         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.272
2025-07-02 06:41:18.272         # do intraline marking on the synch pair
2025-07-02 06:41:18.272         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.272         if eqi is None:
2025-07-02 06:41:18.272             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.272             atags = btags = ""
2025-07-02 06:41:18.272             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.273             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.273                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.273                 if tag == 'replace':
2025-07-02 06:41:18.273                     atags += '^' * la
2025-07-02 06:41:18.273                     btags += '^' * lb
2025-07-02 06:41:18.273                 elif tag == 'delete':
2025-07-02 06:41:18.273                     atags += '-' * la
2025-07-02 06:41:18.273                 elif tag == 'insert':
2025-07-02 06:41:18.273                     btags += '+' * lb
2025-07-02 06:41:18.273                 elif tag == 'equal':
2025-07-02 06:41:18.273                     atags += ' ' * la
2025-07-02 06:41:18.273                     btags += ' ' * lb
2025-07-02 06:41:18.273                 else:
2025-07-02 06:41:18.273                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.273             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.273         else:
2025-07-02 06:41:18.273             # the synch pair is identical
2025-07-02 06:41:18.273             yield '  ' + aelt
2025-07-02 06:41:18.273
2025-07-02 06:41:18.274         # pump out diffs from after the synch point
2025-07-02 06:41:18.274 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.274
2025-07-02 06:41:18.274 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.274 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.274
2025-07-02 06:41:18.274 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.274 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.274 alo = 372, ahi = 1101
2025-07-02 06:41:18.274 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.274 blo = 372, bhi = 1101
2025-07-02 06:41:18.274
2025-07-02 06:41:18.274     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.274         g = []
2025-07-02 06:41:18.274         if alo < ahi:
2025-07-02 06:41:18.274             if blo < bhi:
2025-07-02 06:41:18.274                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.274             else:
2025-07-02 06:41:18.274                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.275         elif blo < bhi:
2025-07-02 06:41:18.275             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.275
2025-07-02 06:41:18.275 >       yield from g
2025-07-02 06:41:18.275
2025-07-02 06:41:18.275 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.275 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.275
2025-07-02 06:41:18.275 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.275 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.275 alo = 372, ahi = 1101
2025-07-02 06:41:18.275 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.275 blo = 372, bhi = 1101
2025-07-02 06:41:18.275
2025-07-02 06:41:18.275     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.275         r"""
2025-07-02 06:41:18.275         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.275         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.275         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.275         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.276
2025-07-02 06:41:18.276         Example:
2025-07-02 06:41:18.276
2025-07-02 06:41:18.276         >>> d = Differ()
2025-07-02 06:41:18.276         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.276         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.276         >>> print(''.join(results), end="")
2025-07-02 06:41:18.276         - abcDefghiJkl
2025-07-02 06:41:18.276         + abcdefGhijkl
2025-07-02 06:41:18.276         """
2025-07-02 06:41:18.276
2025-07-02 06:41:18.276         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.276         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.276         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.276         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.276         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.276
2025-07-02 06:41:18.277         # search for the pair that matches best without being identical
2025-07-02 06:41:18.277         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.277         # on junk -- unless we have to)
2025-07-02 06:41:18.277         for j in range(blo, bhi):
2025-07-02 06:41:18.277             bj = b[j]
2025-07-02 06:41:18.277             cruncher.set_seq2(bj)
2025-07-02 06:41:18.277             for i in range(alo, ahi):
2025-07-02 06:41:18.277                 ai = a[i]
2025-07-02 06:41:18.277                 if ai == bj:
2025-07-02 06:41:18.277                     if eqi is None:
2025-07-02 06:41:18.277                         eqi, eqj = i, j
2025-07-02 06:41:18.277                     continue
2025-07-02 06:41:18.277                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.277                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.277                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.277                 # compares by a factor of 3.
2025-07-02 06:41:18.277                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.277                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.277                 # of the computation is cached by cruncher
2025-07-02 06:41:18.278                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.278                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.278                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.278                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.278         if best_ratio < cutoff:
2025-07-02 06:41:18.278             # no non-identical "pretty close" pair
2025-07-02 06:41:18.278             if eqi is None:
2025-07-02 06:41:18.278                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.278                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.278                 return
2025-07-02 06:41:18.278             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.278             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.278         else:
2025-07-02 06:41:18.278             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.278             eqi = None
2025-07-02 06:41:18.278
2025-07-02 06:41:18.278         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.278         # identical
2025-07-02 06:41:18.279
2025-07-02 06:41:18.279         # pump out diffs from before the synch point
2025-07-02 06:41:18.279         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.279
2025-07-02 06:41:18.279         # do intraline marking on the synch pair
2025-07-02 06:41:18.279         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.279         if eqi is None:
2025-07-02 06:41:18.279             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.279             atags = btags = ""
2025-07-02 06:41:18.279             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.279             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.279                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.279                 if tag == 'replace':
2025-07-02 06:41:18.279                     atags += '^' * la
2025-07-02 06:41:18.279                     btags += '^' * lb
2025-07-02 06:41:18.279                 elif tag == 'delete':
2025-07-02 06:41:18.279                     atags += '-' * la
2025-07-02 06:41:18.279                 elif tag == 'insert':
2025-07-02 06:41:18.279                     btags += '+' * lb
2025-07-02 06:41:18.279                 elif tag == 'equal':
2025-07-02 06:41:18.280                     atags += ' ' * la
2025-07-02 06:41:18.280                     btags += ' ' * lb
2025-07-02 06:41:18.280                 else:
2025-07-02 06:41:18.280                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.280             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.280         else:
2025-07-02 06:41:18.280             # the synch pair is identical
2025-07-02 06:41:18.280             yield '  ' + aelt
2025-07-02 06:41:18.280
2025-07-02 06:41:18.280         # pump out diffs from after the synch point
2025-07-02 06:41:18.280 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.280
2025-07-02 06:41:18.280 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.280 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.280
2025-07-02 06:41:18.280 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.280 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.280 alo = 373, ahi = 1101
2025-07-02 06:41:18.280 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.281 blo = 373, bhi = 1101
2025-07-02 06:41:18.281
2025-07-02 06:41:18.281     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.281         g = []
2025-07-02 06:41:18.281         if alo < ahi:
2025-07-02 06:41:18.281             if blo < bhi:
2025-07-02 06:41:18.281                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.281             else:
2025-07-02 06:41:18.281                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.281         elif blo < bhi:
2025-07-02 06:41:18.281             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.281
2025-07-02 06:41:18.281 >       yield from g
2025-07-02 06:41:18.281
2025-07-02 06:41:18.281 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.281 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.281
2025-07-02 06:41:18.281 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.281 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.282 alo = 373, ahi = 1101
2025-07-02 06:41:18.282 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.282 blo = 373, bhi = 1101
2025-07-02 06:41:18.282
2025-07-02 06:41:18.282     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.282         r"""
2025-07-02 06:41:18.282         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.282         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.282         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.282         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.282
2025-07-02 06:41:18.282         Example:
2025-07-02 06:41:18.282
2025-07-02 06:41:18.282         >>> d = Differ()
2025-07-02 06:41:18.282         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.282         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.282         >>> print(''.join(results), end="")
2025-07-02 06:41:18.283         - abcDefghiJkl
2025-07-02 06:41:18.283         + abcdefGhijkl
2025-07-02 06:41:18.283         """
2025-07-02 06:41:18.283
2025-07-02 06:41:18.283         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.283         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.283         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.283         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.283         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.283
2025-07-02 06:41:18.283         # search for the pair that matches best without being identical
2025-07-02 06:41:18.283         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.283         # on junk -- unless we have to)
2025-07-02 06:41:18.283         for j in range(blo, bhi):
2025-07-02 06:41:18.283             bj = b[j]
2025-07-02 06:41:18.284             cruncher.set_seq2(bj)
2025-07-02 06:41:18.284             for i in range(alo, ahi):
2025-07-02 06:41:18.284                 ai = a[i]
2025-07-02 06:41:18.284                 if ai == bj:
2025-07-02 06:41:18.284                     if eqi is None:
2025-07-02 06:41:18.284                         eqi, eqj = i, j
2025-07-02 06:41:18.284                     continue
2025-07-02 06:41:18.284                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.284                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.284                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.284                 # compares by a factor of 3.
2025-07-02 06:41:18.284                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.284                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.284                 # of the computation is cached by cruncher
2025-07-02 06:41:18.284                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.284                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.285                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.285                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.285         if best_ratio < cutoff:
2025-07-02 06:41:18.285             # no non-identical "pretty close" pair
2025-07-02 06:41:18.285             if eqi is None:
2025-07-02 06:41:18.285                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.285                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.285                 return
2025-07-02 06:41:18.285             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.285             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.285         else:
2025-07-02 06:41:18.285             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.285             eqi = None
2025-07-02 06:41:18.285
2025-07-02 06:41:18.285         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.286         # identical
2025-07-02 06:41:18.286
2025-07-02 06:41:18.286         # pump out diffs from before the synch point
2025-07-02 06:41:18.286         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.286
2025-07-02 06:41:18.286         # do intraline marking on the synch pair
2025-07-02 06:41:18.286         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.286         if eqi is None:
2025-07-02 06:41:18.286             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.286             atags = btags = ""
2025-07-02 06:41:18.286             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.286             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.286                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.286                 if tag == 'replace':
2025-07-02 06:41:18.286                     atags += '^' * la
2025-07-02 06:41:18.286                     btags += '^' * lb
2025-07-02 06:41:18.286                 elif tag == 'delete':
2025-07-02 06:41:18.287                     atags += '-' * la
2025-07-02 06:41:18.287                 elif tag == 'insert':
2025-07-02 06:41:18.287                     btags += '+' * lb
2025-07-02 06:41:18.287                 elif tag == 'equal':
2025-07-02 06:41:18.287                     atags += ' ' * la
2025-07-02 06:41:18.287                     btags += ' ' * lb
2025-07-02 06:41:18.287                 else:
2025-07-02 06:41:18.287                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.287             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.287         else:
2025-07-02 06:41:18.287             # the synch pair is identical
2025-07-02 06:41:18.287             yield '  ' + aelt
2025-07-02 06:41:18.287
2025-07-02 06:41:18.287         # pump out diffs from after the synch point
2025-07-02 06:41:18.288 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.288
2025-07-02 06:41:18.288 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.288 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.288
2025-07-02 06:41:18.288 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.288 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.288 alo = 374, ahi = 1101
2025-07-02 06:41:18.288 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.288 blo = 374, bhi = 1101
2025-07-02 06:41:18.288
2025-07-02 06:41:18.288     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.288         g = []
2025-07-02 06:41:18.289         if alo < ahi:
2025-07-02 06:41:18.289             if blo < bhi:
2025-07-02 06:41:18.289                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.289             else:
2025-07-02 06:41:18.289                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.289         elif blo < bhi:
2025-07-02 06:41:18.289             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.289
2025-07-02 06:41:18.289 >       yield from g
2025-07-02 06:41:18.289
2025-07-02 06:41:18.289 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.289 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.289
2025-07-02 06:41:18.289 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.289 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.289 alo = 374, ahi = 1101
2025-07-02 06:41:18.289 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.290 blo = 374, bhi = 1101
2025-07-02 06:41:18.290
2025-07-02 06:41:18.290     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.290         r"""
2025-07-02 06:41:18.290         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.290         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.290         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.290         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.290
2025-07-02 06:41:18.290         Example:
2025-07-02 06:41:18.290
2025-07-02 06:41:18.290         >>> d = Differ()
2025-07-02 06:41:18.290         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.290         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.290         >>> print(''.join(results), end="")
2025-07-02 06:41:18.290         - abcDefghiJkl
2025-07-02 06:41:18.291         + abcdefGhijkl
2025-07-02 06:41:18.291         """
2025-07-02 06:41:18.291
2025-07-02 06:41:18.291         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.291         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.291         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.291         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.291         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.291
2025-07-02 06:41:18.291         # search for the pair that matches best without being identical
2025-07-02 06:41:18.291         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.291         # on junk -- unless we have to)
2025-07-02 06:41:18.291         for j in range(blo, bhi):
2025-07-02 06:41:18.291             bj = b[j]
2025-07-02 06:41:18.291             cruncher.set_seq2(bj)
2025-07-02 06:41:18.291             for i in range(alo, ahi):
2025-07-02 06:41:18.291                 ai = a[i]
2025-07-02 06:41:18.292                 if ai == bj:
2025-07-02 06:41:18.292                     if eqi is None:
2025-07-02 06:41:18.292                         eqi, eqj = i, j
2025-07-02 06:41:18.292                     continue
2025-07-02 06:41:18.292                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.292                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.292                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.292                 # compares by a factor of 3.
2025-07-02 06:41:18.292                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.292                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.292                 # of the computation is cached by cruncher
2025-07-02 06:41:18.292                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.292                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.292                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.292                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.292         if best_ratio < cutoff:
2025-07-02 06:41:18.292             # no non-identical "pretty close" pair
2025-07-02 06:41:18.292             if eqi is None:
2025-07-02 06:41:18.293                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.293                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.293                 return
2025-07-02 06:41:18.293             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.293             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.293         else:
2025-07-02 06:41:18.293             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.293             eqi = None
2025-07-02 06:41:18.293
2025-07-02 06:41:18.293         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.293         # identical
2025-07-02 06:41:18.293
2025-07-02 06:41:18.293         # pump out diffs from before the synch point
2025-07-02 06:41:18.293         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.293
2025-07-02 06:41:18.293         # do intraline marking on the synch pair
2025-07-02 06:41:18.293         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.294         if eqi is None:
2025-07-02 06:41:18.294             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.294             atags = btags = ""
2025-07-02 06:41:18.294             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.294             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.294                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.294                 if tag == 'replace':
2025-07-02 06:41:18.294                     atags += '^' * la
2025-07-02 06:41:18.294                     btags += '^' * lb
2025-07-02 06:41:18.294                 elif tag == 'delete':
2025-07-02 06:41:18.294                     atags += '-' * la
2025-07-02 06:41:18.294                 elif tag == 'insert':
2025-07-02 06:41:18.294                     btags += '+' * lb
2025-07-02 06:41:18.294                 elif tag == 'equal':
2025-07-02 06:41:18.294                     atags += ' ' * la
2025-07-02 06:41:18.294                     btags += ' ' * lb
2025-07-02 06:41:18.294                 else:
2025-07-02 06:41:18.294                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.295             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.295         else:
2025-07-02 06:41:18.295             # the synch pair is identical
2025-07-02 06:41:18.295             yield '  ' + aelt
2025-07-02 06:41:18.295
2025-07-02 06:41:18.295         # pump out diffs from after the synch point
2025-07-02 06:41:18.295 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.295
2025-07-02 06:41:18.295 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.295 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.295
2025-07-02 06:41:18.295 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.295 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.295 alo = 375, ahi = 1101
2025-07-02 06:41:18.295 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.295 blo = 375, bhi = 1101
2025-07-02 06:41:18.295
2025-07-02 06:41:18.295     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.296         g = []
2025-07-02 06:41:18.296         if alo < ahi:
2025-07-02 06:41:18.296             if blo < bhi:
2025-07-02 06:41:18.296                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.296             else:
2025-07-02 06:41:18.296                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.296         elif blo < bhi:
2025-07-02 06:41:18.296             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.296
2025-07-02 06:41:18.296 >       yield from g
2025-07-02 06:41:18.296
2025-07-02 06:41:18.296 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.296 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.296
2025-07-02 06:41:18.296 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.296 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.296 alo = 375, ahi = 1101
2025-07-02 06:41:18.297 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.297 blo = 375, bhi = 1101
2025-07-02 06:41:18.297
2025-07-02 06:41:18.297     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.297         r"""
2025-07-02 06:41:18.297         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.297         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.297         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.297         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.297
2025-07-02 06:41:18.297         Example:
2025-07-02 06:41:18.297
2025-07-02 06:41:18.297         >>> d = Differ()
2025-07-02 06:41:18.297         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.297         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.297         >>> print(''.join(results), end="")
2025-07-02 06:41:18.297         - abcDefghiJkl
2025-07-02 06:41:18.298         + abcdefGhijkl
2025-07-02 06:41:18.298         """
2025-07-02 06:41:18.298
2025-07-02 06:41:18.298         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.298         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.298         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.298         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.298         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.298
2025-07-02 06:41:18.298         # search for the pair that matches best without being identical
2025-07-02 06:41:18.298         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.298         # on junk -- unless we have to)
2025-07-02 06:41:18.298         for j in range(blo, bhi):
2025-07-02 06:41:18.298             bj = b[j]
2025-07-02 06:41:18.299             cruncher.set_seq2(bj)
2025-07-02 06:41:18.299             for i in range(alo, ahi):
2025-07-02 06:41:18.299                 ai = a[i]
2025-07-02 06:41:18.299                 if ai == bj:
2025-07-02 06:41:18.299                     if eqi is None:
2025-07-02 06:41:18.299                         eqi, eqj = i, j
2025-07-02 06:41:18.299                     continue
2025-07-02 06:41:18.299                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.299                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.299                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.299                 # compares by a factor of 3.
2025-07-02 06:41:18.299                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.299                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.299                 # of the computation is cached by cruncher
2025-07-02 06:41:18.299                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.299                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.299                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.299                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.300         if best_ratio < cutoff:
2025-07-02 06:41:18.300             # no non-identical "pretty close" pair
2025-07-02 06:41:18.300             if eqi is None:
2025-07-02 06:41:18.300                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.300                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.300                 return
2025-07-02 06:41:18.300             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.300             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.300         else:
2025-07-02 06:41:18.300             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.300             eqi = None
2025-07-02 06:41:18.300
2025-07-02 06:41:18.300         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.300         # identical
2025-07-02 06:41:18.300
2025-07-02 06:41:18.300         # pump out diffs from before the synch point
2025-07-02 06:41:18.300         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.300
2025-07-02 06:41:18.301         # do intraline marking on the synch pair
2025-07-02 06:41:18.301         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.301         if eqi is None:
2025-07-02 06:41:18.301             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.301             atags = btags = ""
2025-07-02 06:41:18.301             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.301             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.301                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.301                 if tag == 'replace':
2025-07-02 06:41:18.301                     atags += '^' * la
2025-07-02 06:41:18.301                     btags += '^' * lb
2025-07-02 06:41:18.301                 elif tag == 'delete':
2025-07-02 06:41:18.301                     atags += '-' * la
2025-07-02 06:41:18.301                 elif tag == 'insert':
2025-07-02 06:41:18.301                     btags += '+' * lb
2025-07-02 06:41:18.301                 elif tag == 'equal':
2025-07-02 06:41:18.301                     atags += ' ' * la
2025-07-02 06:41:18.301                     btags += ' ' * lb
2025-07-02 06:41:18.302                 else:
2025-07-02 06:41:18.302                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.302             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.302         else:
2025-07-02 06:41:18.302             # the synch pair is identical
2025-07-02 06:41:18.302             yield '  ' + aelt
2025-07-02 06:41:18.302
2025-07-02 06:41:18.302         # pump out diffs from after the synch point
2025-07-02 06:41:18.302 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.302
2025-07-02 06:41:18.302 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.302 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.302
2025-07-02 06:41:18.302 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.302 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.302 alo = 378, ahi = 1101
2025-07-02 06:41:18.302 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.303 blo = 378, bhi = 1101
2025-07-02 06:41:18.303
2025-07-02 06:41:18.303     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.303         g = []
2025-07-02 06:41:18.303         if alo < ahi:
2025-07-02 06:41:18.303             if blo < bhi:
2025-07-02 06:41:18.303                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.303             else:
2025-07-02 06:41:18.303                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.303         elif blo < bhi:
2025-07-02 06:41:18.303             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.303
2025-07-02 06:41:18.303 >       yield from g
2025-07-02 06:41:18.303
2025-07-02 06:41:18.303 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.303 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.303
2025-07-02 06:41:18.303 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.304 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.304 alo = 378, ahi = 1101
2025-07-02 06:41:18.304 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.304 blo = 378, bhi = 1101
2025-07-02 06:41:18.304
2025-07-02 06:41:18.304     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.304         r"""
2025-07-02 06:41:18.304         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.304         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.304         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.304         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.304
2025-07-02 06:41:18.304         Example:
2025-07-02 06:41:18.304
2025-07-02 06:41:18.304         >>> d = Differ()
2025-07-02 06:41:18.304         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.304         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.304         >>> print(''.join(results), end="")
2025-07-02 06:41:18.305         - abcDefghiJkl
2025-07-02 06:41:18.305         + abcdefGhijkl
2025-07-02 06:41:18.305         """
2025-07-02 06:41:18.305
2025-07-02 06:41:18.305         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.305         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.305         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.305         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.305         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.305
2025-07-02 06:41:18.305         # search for the pair that matches best without being identical
2025-07-02 06:41:18.305         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.305         # on junk -- unless we have to)
2025-07-02 06:41:18.305         for j in range(blo, bhi):
2025-07-02 06:41:18.305             bj = b[j]
2025-07-02 06:41:18.306             cruncher.set_seq2(bj)
2025-07-02 06:41:18.306             for i in range(alo, ahi):
2025-07-02 06:41:18.306                 ai = a[i]
2025-07-02 06:41:18.306                 if ai == bj:
2025-07-02 06:41:18.306                     if eqi is None:
2025-07-02 06:41:18.306                         eqi, eqj = i, j
2025-07-02 06:41:18.306                     continue
2025-07-02 06:41:18.306                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.306                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.306                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.306                 # compares by a factor of 3.
2025-07-02 06:41:18.306                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.306                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.306                 # of the computation is cached by cruncher
2025-07-02 06:41:18.306                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.306                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.306                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.306                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.307         if best_ratio < cutoff:
2025-07-02 06:41:18.307             # no non-identical "pretty close" pair
2025-07-02 06:41:18.307             if eqi is None:
2025-07-02 06:41:18.307                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.307                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.307                 return
2025-07-02 06:41:18.307             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.307             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.307         else:
2025-07-02 06:41:18.307             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.307             eqi = None
2025-07-02 06:41:18.307
2025-07-02 06:41:18.307         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.307         # identical
2025-07-02 06:41:18.307
2025-07-02 06:41:18.307         # pump out diffs from before the synch point
2025-07-02 06:41:18.307         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.308
2025-07-02 06:41:18.308         # do intraline marking on the synch pair
2025-07-02 06:41:18.308         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.308         if eqi is None:
2025-07-02 06:41:18.308             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.308             atags = btags = ""
2025-07-02 06:41:18.308             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.308             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.308                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.308                 if tag == 'replace':
2025-07-02 06:41:18.308                     atags += '^' * la
2025-07-02 06:41:18.308                     btags += '^' * lb
2025-07-02 06:41:18.308                 elif tag == 'delete':
2025-07-02 06:41:18.308                     atags += '-' * la
2025-07-02 06:41:18.308                 elif tag == 'insert':
2025-07-02 06:41:18.308                     btags += '+' * lb
2025-07-02 06:41:18.308                 elif tag == 'equal':
2025-07-02 06:41:18.309                     atags += ' ' * la
2025-07-02 06:41:18.309                     btags += ' ' * lb
2025-07-02 06:41:18.309                 else:
2025-07-02 06:41:18.309                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.309             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.309         else:
2025-07-02 06:41:18.309             # the synch pair is identical
2025-07-02 06:41:18.309             yield '  ' + aelt
2025-07-02 06:41:18.309
2025-07-02 06:41:18.309         # pump out diffs from after the synch point
2025-07-02 06:41:18.309 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.309
2025-07-02 06:41:18.309 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.309 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.309
2025-07-02 06:41:18.309 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.309 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.309 alo = 379, ahi = 1101
2025-07-02 06:41:18.310 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.310 blo = 379, bhi = 1101
2025-07-02 06:41:18.310
2025-07-02 06:41:18.310     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.310         g = []
2025-07-02 06:41:18.310         if alo < ahi:
2025-07-02 06:41:18.310             if blo < bhi:
2025-07-02 06:41:18.310                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.310             else:
2025-07-02 06:41:18.310                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.310         elif blo < bhi:
2025-07-02 06:41:18.310             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.310
2025-07-02 06:41:18.310 >       yield from g
2025-07-02 06:41:18.310
2025-07-02 06:41:18.310 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.310 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.310
2025-07-02 06:41:18.311 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.311 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.311 alo = 379, ahi = 1101
2025-07-02 06:41:18.311 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.311 blo = 379, bhi = 1101
2025-07-02 06:41:18.311
2025-07-02 06:41:18.311     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.311         r"""
2025-07-02 06:41:18.311         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.311         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.311         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.311         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.311
2025-07-02 06:41:18.311         Example:
2025-07-02 06:41:18.311
2025-07-02 06:41:18.311         >>> d = Differ()
2025-07-02 06:41:18.311         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.311         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.312         >>> print(''.join(results), end="")
2025-07-02 06:41:18.312         - abcDefghiJkl
2025-07-02 06:41:18.312         + abcdefGhijkl
2025-07-02 06:41:18.312         """
2025-07-02 06:41:18.312
2025-07-02 06:41:18.312         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.312         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.312         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.312         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.312         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.312
2025-07-02 06:41:18.312         # search for the pair that matches best without being identical
2025-07-02 06:41:18.312         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.312         # on junk -- unless we have to)
2025-07-02 06:41:18.312         for j in range(blo, bhi):
2025-07-02 06:41:18.312             bj = b[j]
2025-07-02 06:41:18.313             cruncher.set_seq2(bj)
2025-07-02 06:41:18.313             for i in range(alo, ahi):
2025-07-02 06:41:18.313                 ai = a[i]
2025-07-02 06:41:18.313                 if ai == bj:
2025-07-02 06:41:18.313                     if eqi is None:
2025-07-02 06:41:18.313                         eqi, eqj = i, j
2025-07-02 06:41:18.313                     continue
2025-07-02 06:41:18.313                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.313                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.313                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.313                 # compares by a factor of 3.
2025-07-02 06:41:18.313                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.313                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.313                 # of the computation is cached by cruncher
2025-07-02 06:41:18.313                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.313                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.313                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.313                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.314         if best_ratio < cutoff:
2025-07-02 06:41:18.314             # no non-identical "pretty close" pair
2025-07-02 06:41:18.314             if eqi is None:
2025-07-02 06:41:18.314                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.314                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.314                 return
2025-07-02 06:41:18.314             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.314             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.314         else:
2025-07-02 06:41:18.314             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.314             eqi = None
2025-07-02 06:41:18.314
2025-07-02 06:41:18.314         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.314         # identical
2025-07-02 06:41:18.314
2025-07-02 06:41:18.314         # pump out diffs from before the synch point
2025-07-02 06:41:18.314         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.314
2025-07-02 06:41:18.315         # do intraline marking on the synch pair
2025-07-02 06:41:18.315         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.315         if eqi is None:
2025-07-02 06:41:18.315             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.315             atags = btags = ""
2025-07-02 06:41:18.315             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.315             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.315                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.315                 if tag == 'replace':
2025-07-02 06:41:18.315                     atags += '^' * la
2025-07-02 06:41:18.315                     btags += '^' * lb
2025-07-02 06:41:18.315                 elif tag == 'delete':
2025-07-02 06:41:18.315                     atags += '-' * la
2025-07-02 06:41:18.315                 elif tag == 'insert':
2025-07-02 06:41:18.315                     btags += '+' * lb
2025-07-02 06:41:18.315                 elif tag == 'equal':
2025-07-02 06:41:18.315                     atags += ' ' * la
2025-07-02 06:41:18.315                     btags += ' ' * lb
2025-07-02 06:41:18.316                 else:
2025-07-02 06:41:18.316                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.316             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.316         else:
2025-07-02 06:41:18.316             # the synch pair is identical
2025-07-02 06:41:18.316             yield '  ' + aelt
2025-07-02 06:41:18.316
2025-07-02 06:41:18.316         # pump out diffs from after the synch point
2025-07-02 06:41:18.316 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.316
2025-07-02 06:41:18.316 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.316 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.316
2025-07-02 06:41:18.316 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.316 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.316 alo = 380, ahi = 1101
2025-07-02 06:41:18.316 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.317 blo = 380, bhi = 1101
2025-07-02 06:41:18.317
2025-07-02 06:41:18.317     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.317         g = []
2025-07-02 06:41:18.317         if alo < ahi:
2025-07-02 06:41:18.317             if blo < bhi:
2025-07-02 06:41:18.317                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.317             else:
2025-07-02 06:41:18.317                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.317         elif blo < bhi:
2025-07-02 06:41:18.317             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.317
2025-07-02 06:41:18.317 >       yield from g
2025-07-02 06:41:18.317
2025-07-02 06:41:18.317 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.317 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.317
2025-07-02 06:41:18.318 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.318 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.318 alo = 380, ahi = 1101
2025-07-02 06:41:18.318 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.318 blo = 380, bhi = 1101
2025-07-02 06:41:18.318
2025-07-02 06:41:18.318     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.318         r"""
2025-07-02 06:41:18.318         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.318         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.318         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.318         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.318
2025-07-02 06:41:18.318         Example:
2025-07-02 06:41:18.318
2025-07-02 06:41:18.318         >>> d = Differ()
2025-07-02 06:41:18.318         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.319         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.319         >>> print(''.join(results), end="")
2025-07-02 06:41:18.319         - abcDefghiJkl
2025-07-02 06:41:18.319         + abcdefGhijkl
2025-07-02 06:41:18.319         """
2025-07-02 06:41:18.319
2025-07-02 06:41:18.319         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.319         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.319         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.319         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.319         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.319
2025-07-02 06:41:18.319         # search for the pair that matches best without being identical
2025-07-02 06:41:18.319         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.319         # on junk -- unless we have to)
2025-07-02 06:41:18.319         for j in range(blo, bhi):
2025-07-02 06:41:18.320             bj = b[j]
2025-07-02 06:41:18.320             cruncher.set_seq2(bj)
2025-07-02 06:41:18.320             for i in range(alo, ahi):
2025-07-02 06:41:18.320                 ai = a[i]
2025-07-02 06:41:18.320                 if ai == bj:
2025-07-02 06:41:18.320                     if eqi is None:
2025-07-02 06:41:18.320                         eqi, eqj = i, j
2025-07-02 06:41:18.320                     continue
2025-07-02 06:41:18.320                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.320                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.320                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.320                 # compares by a factor of 3.
2025-07-02 06:41:18.320                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.320                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.320                 # of the computation is cached by cruncher
2025-07-02 06:41:18.320                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.320                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.320                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.321                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.321         if best_ratio < cutoff:
2025-07-02 06:41:18.321             # no non-identical "pretty close" pair
2025-07-02 06:41:18.321             if eqi is None:
2025-07-02 06:41:18.321                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.321                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.321                 return
2025-07-02 06:41:18.321             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.321             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.321         else:
2025-07-02 06:41:18.321             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.321             eqi = None
2025-07-02 06:41:18.321
2025-07-02 06:41:18.321         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.321         # identical
2025-07-02 06:41:18.321
2025-07-02 06:41:18.321         # pump out diffs from before the synch point
2025-07-02 06:41:18.321         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.322
2025-07-02 06:41:18.322         # do intraline marking on the synch pair
2025-07-02 06:41:18.322         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.322         if eqi is None:
2025-07-02 06:41:18.322             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.322             atags = btags = ""
2025-07-02 06:41:18.322             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.322             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.322                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.322                 if tag == 'replace':
2025-07-02 06:41:18.322                     atags += '^' * la
2025-07-02 06:41:18.322                     btags += '^' * lb
2025-07-02 06:41:18.322                 elif tag == 'delete':
2025-07-02 06:41:18.322                     atags += '-' * la
2025-07-02 06:41:18.322                 elif tag == 'insert':
2025-07-02 06:41:18.322                     btags += '+' * lb
2025-07-02 06:41:18.322                 elif tag == 'equal':
2025-07-02 06:41:18.322                     atags += ' ' * la
2025-07-02 06:41:18.323                     btags += ' ' * lb
2025-07-02 06:41:18.323                 else:
2025-07-02 06:41:18.323                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.323             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.323         else:
2025-07-02 06:41:18.323             # the synch pair is identical
2025-07-02 06:41:18.323             yield '  ' + aelt
2025-07-02 06:41:18.323
2025-07-02 06:41:18.323         # pump out diffs from after the synch point
2025-07-02 06:41:18.323 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.323
2025-07-02 06:41:18.323 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.323 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.323
2025-07-02 06:41:18.323 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.323 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.324 alo = 381, ahi = 1101
2025-07-02 06:41:18.324 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.324 blo = 381, bhi = 1101
2025-07-02 06:41:18.324
2025-07-02 06:41:18.324     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.324         g = []
2025-07-02 06:41:18.324         if alo < ahi:
2025-07-02 06:41:18.324             if blo < bhi:
2025-07-02 06:41:18.324                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.324             else:
2025-07-02 06:41:18.324                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.324         elif blo < bhi:
2025-07-02 06:41:18.324             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.324
2025-07-02 06:41:18.324 >       yield from g
2025-07-02 06:41:18.324
2025-07-02 06:41:18.324 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.325 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.325
2025-07-02 06:41:18.325 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.325 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.325 alo = 381, ahi = 1101
2025-07-02 06:41:18.325 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.325 blo = 381, bhi = 1101
2025-07-02 06:41:18.325
2025-07-02 06:41:18.325     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.325         r"""
2025-07-02 06:41:18.325         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.325         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.325         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.325         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.325
2025-07-02 06:41:18.326         Example:
2025-07-02 06:41:18.326
2025-07-02 06:41:18.326         >>> d = Differ()
2025-07-02 06:41:18.326         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.326         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.326         >>> print(''.join(results), end="")
2025-07-02 06:41:18.326         - abcDefghiJkl
2025-07-02 06:41:18.326         + abcdefGhijkl
2025-07-02 06:41:18.326         """
2025-07-02 06:41:18.326
2025-07-02 06:41:18.326         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.326         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.326         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.326         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.326         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.327
2025-07-02 06:41:18.327         # search for the pair that matches best without being identical
2025-07-02 06:41:18.327         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.327         # on junk -- unless we have to)
2025-07-02 06:41:18.327         for j in range(blo, bhi):
2025-07-02 06:41:18.327             bj = b[j]
2025-07-02 06:41:18.327             cruncher.set_seq2(bj)
2025-07-02 06:41:18.327             for i in range(alo, ahi):
2025-07-02 06:41:18.327                 ai = a[i]
2025-07-02 06:41:18.327                 if ai == bj:
2025-07-02 06:41:18.327                     if eqi is None:
2025-07-02 06:41:18.327                         eqi, eqj = i, j
2025-07-02 06:41:18.327                     continue
2025-07-02 06:41:18.327                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.327                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.327                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.327                 # compares by a factor of 3.
2025-07-02 06:41:18.327                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.328                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.328                 # of the computation is cached by cruncher
2025-07-02 06:41:18.328                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.328                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.328                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.328                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.328         if best_ratio < cutoff:
2025-07-02 06:41:18.328             # no non-identical "pretty close" pair
2025-07-02 06:41:18.328             if eqi is None:
2025-07-02 06:41:18.328                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.328                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.328                 return
2025-07-02 06:41:18.328             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.328             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.328         else:
2025-07-02 06:41:18.328             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.328             eqi = None
2025-07-02 06:41:18.328
2025-07-02 06:41:18.329         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.329         # identical
2025-07-02 06:41:18.329
2025-07-02 06:41:18.329         # pump out diffs from before the synch point
2025-07-02 06:41:18.329         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.329
2025-07-02 06:41:18.329         # do intraline marking on the synch pair
2025-07-02 06:41:18.329         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.329         if eqi is None:
2025-07-02 06:41:18.329             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.329             atags = btags = ""
2025-07-02 06:41:18.329             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.329             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.329                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.329                 if tag == 'replace':
2025-07-02 06:41:18.329                     atags += '^' * la
2025-07-02 06:41:18.329                     btags += '^' * lb
2025-07-02 06:41:18.329                 elif tag == 'delete':
2025-07-02 06:41:18.330                     atags += '-' * la
2025-07-02 06:41:18.330                 elif tag == 'insert':
2025-07-02 06:41:18.330                     btags += '+' * lb
2025-07-02 06:41:18.330                 elif tag == 'equal':
2025-07-02 06:41:18.330                     atags += ' ' * la
2025-07-02 06:41:18.330                     btags += ' ' * lb
2025-07-02 06:41:18.330                 else:
2025-07-02 06:41:18.330                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.330             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.330         else:
2025-07-02 06:41:18.330             # the synch pair is identical
2025-07-02 06:41:18.330             yield '  ' + aelt
2025-07-02 06:41:18.330
2025-07-02 06:41:18.330         # pump out diffs from after the synch point
2025-07-02 06:41:18.330 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.330
2025-07-02 06:41:18.330 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.330 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.331
2025-07-02 06:41:18.331 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.331 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.331 alo = 382, ahi = 1101
2025-07-02 06:41:18.331 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.331 blo = 382, bhi = 1101
2025-07-02 06:41:18.331
2025-07-02 06:41:18.331     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.331         g = []
2025-07-02 06:41:18.331         if alo < ahi:
2025-07-02 06:41:18.331             if blo < bhi:
2025-07-02 06:41:18.331                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.331             else:
2025-07-02 06:41:18.331                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.331         elif blo < bhi:
2025-07-02 06:41:18.331             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.331
2025-07-02 06:41:18.331 >       yield from g
2025-07-02 06:41:18.332
2025-07-02 06:41:18.332 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.332 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.332
2025-07-02 06:41:18.332 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.332 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.332 alo = 382, ahi = 1101
2025-07-02 06:41:18.332 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.332 blo = 382, bhi = 1101
2025-07-02 06:41:18.332
2025-07-02 06:41:18.332     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.332         r"""
2025-07-02 06:41:18.332         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.332         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.332         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.332         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.332
2025-07-02 06:41:18.332         Example:
2025-07-02 06:41:18.333
2025-07-02 06:41:18.333         >>> d = Differ()
2025-07-02 06:41:18.333         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.333         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.333         >>> print(''.join(results), end="")
2025-07-02 06:41:18.333         - abcDefghiJkl
2025-07-02 06:41:18.333         + abcdefGhijkl
2025-07-02 06:41:18.333         """
2025-07-02 06:41:18.333
2025-07-02 06:41:18.333         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.333         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.333         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.333         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.333         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.333
2025-07-02 06:41:18.333         # search for the pair that matches best without being identical
2025-07-02 06:41:18.333         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.334         # on junk -- unless we have to)
2025-07-02 06:41:18.334         for j in range(blo, bhi):
2025-07-02 06:41:18.334             bj = b[j]
2025-07-02 06:41:18.334             cruncher.set_seq2(bj)
2025-07-02 06:41:18.334             for i in range(alo, ahi):
2025-07-02 06:41:18.334                 ai = a[i]
2025-07-02 06:41:18.334                 if ai == bj:
2025-07-02 06:41:18.334                     if eqi is None:
2025-07-02 06:41:18.334                         eqi, eqj = i, j
2025-07-02 06:41:18.334                     continue
2025-07-02 06:41:18.334                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.334                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.334                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.334                 # compares by a factor of 3.
2025-07-02 06:41:18.334                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.334                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.334                 # of the computation is cached by cruncher
2025-07-02 06:41:18.334                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.334                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.334                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.335                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.335         if best_ratio < cutoff:
2025-07-02 06:41:18.335             # no non-identical "pretty close" pair
2025-07-02 06:41:18.335             if eqi is None:
2025-07-02 06:41:18.335                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.335                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.335                 return
2025-07-02 06:41:18.335             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.335             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.335         else:
2025-07-02 06:41:18.335             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.335             eqi = None
2025-07-02 06:41:18.335
2025-07-02 06:41:18.335         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.335         # identical
2025-07-02 06:41:18.335
2025-07-02 06:41:18.335         # pump out diffs from before the synch point
2025-07-02 06:41:18.335         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.336
2025-07-02 06:41:18.336         # do intraline marking on the synch pair
2025-07-02 06:41:18.336         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.336         if eqi is None:
2025-07-02 06:41:18.336             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.336             atags = btags = ""
2025-07-02 06:41:18.336             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.336             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.336                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.336                 if tag == 'replace':
2025-07-02 06:41:18.336                     atags += '^' * la
2025-07-02 06:41:18.336                     btags += '^' * lb
2025-07-02 06:41:18.336                 elif tag == 'delete':
2025-07-02 06:41:18.336                     atags += '-' * la
2025-07-02 06:41:18.336                 elif tag == 'insert':
2025-07-02 06:41:18.336                     btags += '+' * lb
2025-07-02 06:41:18.336                 elif tag == 'equal':
2025-07-02 06:41:18.336                     atags += ' ' * la
2025-07-02 06:41:18.336                     btags += ' ' * lb
2025-07-02 06:41:18.337                 else:
2025-07-02 06:41:18.337                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.337             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.337         else:
2025-07-02 06:41:18.337             # the synch pair is identical
2025-07-02 06:41:18.337             yield '  ' + aelt
2025-07-02 06:41:18.337
2025-07-02 06:41:18.337         # pump out diffs from after the synch point
2025-07-02 06:41:18.337 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.337
2025-07-02 06:41:18.337 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.337 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.337
2025-07-02 06:41:18.337 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.337 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.337 alo = 383, ahi = 1101
2025-07-02 06:41:18.337 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.337 blo = 383, bhi = 1101
2025-07-02 06:41:18.337
2025-07-02 06:41:18.338     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.338         g = []
2025-07-02 06:41:18.338         if alo < ahi:
2025-07-02 06:41:18.338             if blo < bhi:
2025-07-02 06:41:18.338                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.338             else:
2025-07-02 06:41:18.338                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.338         elif blo < bhi:
2025-07-02 06:41:18.338             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.338
2025-07-02 06:41:18.338 >       yield from g
2025-07-02 06:41:18.338
2025-07-02 06:41:18.338 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.338 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.338
2025-07-02 06:41:18.338 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.338 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.338 alo = 383, ahi = 1101
2025-07-02 06:41:18.338 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.339 blo = 383, bhi = 1101
2025-07-02 06:41:18.339
2025-07-02 06:41:18.339     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.339         r"""
2025-07-02 06:41:18.339         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.339         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.339         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.339         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.339
2025-07-02 06:41:18.339         Example:
2025-07-02 06:41:18.339
2025-07-02 06:41:18.339         >>> d = Differ()
2025-07-02 06:41:18.339         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.339         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.339         >>> print(''.join(results), end="")
2025-07-02 06:41:18.339         - abcDefghiJkl
2025-07-02 06:41:18.339         + abcdefGhijkl
2025-07-02 06:41:18.340         """
2025-07-02 06:41:18.340
2025-07-02 06:41:18.340         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.340         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.340         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.340         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.340         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.340
2025-07-02 06:41:18.340         # search for the pair that matches best without being identical
2025-07-02 06:41:18.340         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.340         # on junk -- unless we have to)
2025-07-02 06:41:18.340         for j in range(blo, bhi):
2025-07-02 06:41:18.340             bj = b[j]
2025-07-02 06:41:18.340             cruncher.set_seq2(bj)
2025-07-02 06:41:18.340             for i in range(alo, ahi):
2025-07-02 06:41:18.340                 ai = a[i]
2025-07-02 06:41:18.340                 if ai == bj:
2025-07-02 06:41:18.340                     if eqi is None:
2025-07-02 06:41:18.340                         eqi, eqj = i, j
2025-07-02 06:41:18.341                     continue
2025-07-02 06:41:18.341                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.341                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.341                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.341                 # compares by a factor of 3.
2025-07-02 06:41:18.341                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.341                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.341                 # of the computation is cached by cruncher
2025-07-02 06:41:18.341                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.341                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.341                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.341                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.341         if best_ratio < cutoff:
2025-07-02 06:41:18.341             # no non-identical "pretty close" pair
2025-07-02 06:41:18.341             if eqi is None:
2025-07-02 06:41:18.341                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.341                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.341                 return
2025-07-02 06:41:18.341             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.342             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.342         else:
2025-07-02 06:41:18.342             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.342             eqi = None
2025-07-02 06:41:18.342
2025-07-02 06:41:18.342         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.342         # identical
2025-07-02 06:41:18.342
2025-07-02 06:41:18.342         # pump out diffs from before the synch point
2025-07-02 06:41:18.342         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.342
2025-07-02 06:41:18.342         # do intraline marking on the synch pair
2025-07-02 06:41:18.342         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.342         if eqi is None:
2025-07-02 06:41:18.342             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.342             atags = btags = ""
2025-07-02 06:41:18.342             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.342             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.342                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.342                 if tag == 'replace':
2025-07-02 06:41:18.343                     atags += '^' * la
2025-07-02 06:41:18.343                     btags += '^' * lb
2025-07-02 06:41:18.343                 elif tag == 'delete':
2025-07-02 06:41:18.343                     atags += '-' * la
2025-07-02 06:41:18.343                 elif tag == 'insert':
2025-07-02 06:41:18.343                     btags += '+' * lb
2025-07-02 06:41:18.343                 elif tag == 'equal':
2025-07-02 06:41:18.343                     atags += ' ' * la
2025-07-02 06:41:18.343                     btags += ' ' * lb
2025-07-02 06:41:18.343                 else:
2025-07-02 06:41:18.343                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.343             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.343         else:
2025-07-02 06:41:18.343             # the synch pair is identical
2025-07-02 06:41:18.343             yield '  ' + aelt
2025-07-02 06:41:18.343
2025-07-02 06:41:18.343         # pump out diffs from after the synch point
2025-07-02 06:41:18.343 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.343
2025-07-02 06:41:18.343 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.343 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.344
2025-07-02 06:41:18.344 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.344 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.344 alo = 384, ahi = 1101
2025-07-02 06:41:18.344 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.344 blo = 384, bhi = 1101
2025-07-02 06:41:18.344
2025-07-02 06:41:18.344     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.344         g = []
2025-07-02 06:41:18.344         if alo < ahi:
2025-07-02 06:41:18.344             if blo < bhi:
2025-07-02 06:41:18.344                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.344             else:
2025-07-02 06:41:18.344                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.344         elif blo < bhi:
2025-07-02 06:41:18.344             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.344
2025-07-02 06:41:18.344 >       yield from g
2025-07-02 06:41:18.344
2025-07-02 06:41:18.344 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.345 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.345
2025-07-02 06:41:18.345 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.345 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.345 alo = 384, ahi = 1101
2025-07-02 06:41:18.345 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.345 blo = 384, bhi = 1101
2025-07-02 06:41:18.345
2025-07-02 06:41:18.345     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.345         r"""
2025-07-02 06:41:18.345         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.345         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.345         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.345         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.345
2025-07-02 06:41:18.345         Example:
2025-07-02 06:41:18.345
2025-07-02 06:41:18.346         >>> d = Differ()
2025-07-02 06:41:18.346         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.346         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.346         >>> print(''.join(results), end="")
2025-07-02 06:41:18.346         - abcDefghiJkl
2025-07-02 06:41:18.346         + abcdefGhijkl
2025-07-02 06:41:18.346         """
2025-07-02 06:41:18.346
2025-07-02 06:41:18.346         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.346         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.346         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.346         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.346         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.346
2025-07-02 06:41:18.346         # search for the pair that matches best without being identical
2025-07-02 06:41:18.346         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.346         # on junk -- unless we have to)
2025-07-02 06:41:18.346         for j in range(blo, bhi):
2025-07-02 06:41:18.347             bj = b[j]
2025-07-02 06:41:18.347             cruncher.set_seq2(bj)
2025-07-02 06:41:18.347             for i in range(alo, ahi):
2025-07-02 06:41:18.347                 ai = a[i]
2025-07-02 06:41:18.347                 if ai == bj:
2025-07-02 06:41:18.347                     if eqi is None:
2025-07-02 06:41:18.347                         eqi, eqj = i, j
2025-07-02 06:41:18.347                     continue
2025-07-02 06:41:18.347                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.347                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.347                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.347                 # compares by a factor of 3.
2025-07-02 06:41:18.347                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.347                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.347                 # of the computation is cached by cruncher
2025-07-02 06:41:18.347                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.347                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.347                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.347                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.347         if best_ratio < cutoff:
2025-07-02 06:41:18.348             # no non-identical "pretty close" pair
2025-07-02 06:41:18.348             if eqi is None:
2025-07-02 06:41:18.348                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.348                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.348                 return
2025-07-02 06:41:18.348             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.348             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.348         else:
2025-07-02 06:41:18.348             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.348             eqi = None
2025-07-02 06:41:18.348
2025-07-02 06:41:18.348         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.348         # identical
2025-07-02 06:41:18.348
2025-07-02 06:41:18.348         # pump out diffs from before the synch point
2025-07-02 06:41:18.348         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.348
2025-07-02 06:41:18.348         # do intraline marking on the synch pair
2025-07-02 06:41:18.348         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.348         if eqi is None:
2025-07-02 06:41:18.349             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.349             atags = btags = ""
2025-07-02 06:41:18.349             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.349             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.349                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.349                 if tag == 'replace':
2025-07-02 06:41:18.349                     atags += '^' * la
2025-07-02 06:41:18.349                     btags += '^' * lb
2025-07-02 06:41:18.349                 elif tag == 'delete':
2025-07-02 06:41:18.349                     atags += '-' * la
2025-07-02 06:41:18.349                 elif tag == 'insert':
2025-07-02 06:41:18.349                     btags += '+' * lb
2025-07-02 06:41:18.349                 elif tag == 'equal':
2025-07-02 06:41:18.349                     atags += ' ' * la
2025-07-02 06:41:18.349                     btags += ' ' * lb
2025-07-02 06:41:18.349                 else:
2025-07-02 06:41:18.349                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.349             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.349         else:
2025-07-02 06:41:18.349             # the synch pair is identical
2025-07-02 06:41:18.349             yield '  ' + aelt
2025-07-02 06:41:18.350
2025-07-02 06:41:18.350         # pump out diffs from after the synch point
2025-07-02 06:41:18.350 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.350
2025-07-02 06:41:18.350 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.350 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.350
2025-07-02 06:41:18.350 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.350 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.350 alo = 385, ahi = 1101
2025-07-02 06:41:18.350 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.350 blo = 385, bhi = 1101
2025-07-02 06:41:18.350
2025-07-02 06:41:18.350     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.350         g = []
2025-07-02 06:41:18.350         if alo < ahi:
2025-07-02 06:41:18.350             if blo < bhi:
2025-07-02 06:41:18.350                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.350             else:
2025-07-02 06:41:18.350                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.351         elif blo < bhi:
2025-07-02 06:41:18.351             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.351
2025-07-02 06:41:18.351 >       yield from g
2025-07-02 06:41:18.351
2025-07-02 06:41:18.351 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.351 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.351
2025-07-02 06:41:18.351 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.351 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.351 alo = 385, ahi = 1101
2025-07-02 06:41:18.351 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.351 blo = 385, bhi = 1101
2025-07-02 06:41:18.351
2025-07-02 06:41:18.351     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.351         r"""
2025-07-02 06:41:18.351         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.351         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.351         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.351         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.352
2025-07-02 06:41:18.352         Example:
2025-07-02 06:41:18.352
2025-07-02 06:41:18.352         >>> d = Differ()
2025-07-02 06:41:18.352         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.352         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.352         >>> print(''.join(results), end="")
2025-07-02 06:41:18.352         - abcDefghiJkl
2025-07-02 06:41:18.352         + abcdefGhijkl
2025-07-02 06:41:18.352         """
2025-07-02 06:41:18.352
2025-07-02 06:41:18.352         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.352         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.352         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.352         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.352         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.352
2025-07-02 06:41:18.352         # search for the pair that matches best without being identical
2025-07-02 06:41:18.352         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.353         # on junk -- unless we have to)
2025-07-02 06:41:18.353         for j in range(blo, bhi):
2025-07-02 06:41:18.353             bj = b[j]
2025-07-02 06:41:18.353             cruncher.set_seq2(bj)
2025-07-02 06:41:18.353             for i in range(alo, ahi):
2025-07-02 06:41:18.353                 ai = a[i]
2025-07-02 06:41:18.353                 if ai == bj:
2025-07-02 06:41:18.353                     if eqi is None:
2025-07-02 06:41:18.353                         eqi, eqj = i, j
2025-07-02 06:41:18.353                     continue
2025-07-02 06:41:18.353                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.353                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.353                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.353                 # compares by a factor of 3.
2025-07-02 06:41:18.353                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.353                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.353                 # of the computation is cached by cruncher
2025-07-02 06:41:18.353                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.353                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.354                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.354                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.354         if best_ratio < cutoff:
2025-07-02 06:41:18.354             # no non-identical "pretty close" pair
2025-07-02 06:41:18.354             if eqi is None:
2025-07-02 06:41:18.354                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.354                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.354                 return
2025-07-02 06:41:18.354             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.354             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.354         else:
2025-07-02 06:41:18.354             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.354             eqi = None
2025-07-02 06:41:18.354
2025-07-02 06:41:18.354         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.354         # identical
2025-07-02 06:41:18.354
2025-07-02 06:41:18.354         # pump out diffs from before the synch point
2025-07-02 06:41:18.354         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.355
2025-07-02 06:41:18.355         # do intraline marking on the synch pair
2025-07-02 06:41:18.355         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.355         if eqi is None:
2025-07-02 06:41:18.355             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.355             atags = btags = ""
2025-07-02 06:41:18.355             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.355             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.355                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.355                 if tag == 'replace':
2025-07-02 06:41:18.355                     atags += '^' * la
2025-07-02 06:41:18.355                     btags += '^' * lb
2025-07-02 06:41:18.355                 elif tag == 'delete':
2025-07-02 06:41:18.355                     atags += '-' * la
2025-07-02 06:41:18.355                 elif tag == 'insert':
2025-07-02 06:41:18.355                     btags += '+' * lb
2025-07-02 06:41:18.355                 elif tag == 'equal':
2025-07-02 06:41:18.355                     atags += ' ' * la
2025-07-02 06:41:18.355                     btags += ' ' * lb
2025-07-02 06:41:18.355                 else:
2025-07-02 06:41:18.356                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.356             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.356         else:
2025-07-02 06:41:18.356             # the synch pair is identical
2025-07-02 06:41:18.356             yield '  ' + aelt
2025-07-02 06:41:18.356
2025-07-02 06:41:18.356         # pump out diffs from after the synch point
2025-07-02 06:41:18.356 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.356
2025-07-02 06:41:18.356 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.356 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.356
2025-07-02 06:41:18.356 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.356 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.356 alo = 386, ahi = 1101
2025-07-02 06:41:18.356 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.356 blo = 386, bhi = 1101
2025-07-02 06:41:18.356
2025-07-02 06:41:18.356     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.356         g = []
2025-07-02 06:41:18.357         if alo < ahi:
2025-07-02 06:41:18.357             if blo < bhi:
2025-07-02 06:41:18.357                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.357             else:
2025-07-02 06:41:18.357                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.357         elif blo < bhi:
2025-07-02 06:41:18.357             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.357
2025-07-02 06:41:18.357 >       yield from g
2025-07-02 06:41:18.357
2025-07-02 06:41:18.357 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.357 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.357
2025-07-02 06:41:18.357 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.357 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.357 alo = 386, ahi = 1101
2025-07-02 06:41:18.357 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.357 blo = 386, bhi = 1101
2025-07-02 06:41:18.358
2025-07-02 06:41:18.358     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.358         r"""
2025-07-02 06:41:18.358         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.358         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.358         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.358         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.358
2025-07-02 06:41:18.358         Example:
2025-07-02 06:41:18.358
2025-07-02 06:41:18.358         >>> d = Differ()
2025-07-02 06:41:18.358         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.358         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.358         >>> print(''.join(results), end="")
2025-07-02 06:41:18.358         - abcDefghiJkl
2025-07-02 06:41:18.358         + abcdefGhijkl
2025-07-02 06:41:18.358         """
2025-07-02 06:41:18.358
2025-07-02 06:41:18.359         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.359         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.359         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.359         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.359         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.359
2025-07-02 06:41:18.359         # search for the pair that matches best without being identical
2025-07-02 06:41:18.359         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.359         # on junk -- unless we have to)
2025-07-02 06:41:18.359         for j in range(blo, bhi):
2025-07-02 06:41:18.359             bj = b[j]
2025-07-02 06:41:18.359             cruncher.set_seq2(bj)
2025-07-02 06:41:18.359             for i in range(alo, ahi):
2025-07-02 06:41:18.359                 ai = a[i]
2025-07-02 06:41:18.359                 if ai == bj:
2025-07-02 06:41:18.359                     if eqi is None:
2025-07-02 06:41:18.359                         eqi, eqj = i, j
2025-07-02 06:41:18.359                     continue
2025-07-02 06:41:18.359                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.359                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.359                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.360                 # compares by a factor of 3.
2025-07-02 06:41:18.360                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.360                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.360                 # of the computation is cached by cruncher
2025-07-02 06:41:18.360                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.360                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.360                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.360                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.360         if best_ratio < cutoff:
2025-07-02 06:41:18.360             # no non-identical "pretty close" pair
2025-07-02 06:41:18.360             if eqi is None:
2025-07-02 06:41:18.360                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.360                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.360                 return
2025-07-02 06:41:18.360             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.360             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.360         else:
2025-07-02 06:41:18.360             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.360             eqi = None
2025-07-02 06:41:18.360
2025-07-02 06:41:18.361         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.361         # identical
2025-07-02 06:41:18.361
2025-07-02 06:41:18.361         # pump out diffs from before the synch point
2025-07-02 06:41:18.361         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.361
2025-07-02 06:41:18.361         # do intraline marking on the synch pair
2025-07-02 06:41:18.361         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.361         if eqi is None:
2025-07-02 06:41:18.361             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.361             atags = btags = ""
2025-07-02 06:41:18.361             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.361             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.361                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.361                 if tag == 'replace':
2025-07-02 06:41:18.364                     atags += '^' * la
2025-07-02 06:41:18.364                     btags += '^' * lb
2025-07-02 06:41:18.364                 elif tag == 'delete':
2025-07-02 06:41:18.364                     atags += '-' * la
2025-07-02 06:41:18.364                 elif tag == 'insert':
2025-07-02 06:41:18.364                     btags += '+' * lb
2025-07-02 06:41:18.364                 elif tag == 'equal':
2025-07-02 06:41:18.364                     atags += ' ' * la
2025-07-02 06:41:18.364                     btags += ' ' * lb
2025-07-02 06:41:18.364                 else:
2025-07-02 06:41:18.364                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.364             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.364         else:
2025-07-02 06:41:18.364             # the synch pair is identical
2025-07-02 06:41:18.364             yield '  ' + aelt
2025-07-02 06:41:18.364
2025-07-02 06:41:18.364         # pump out diffs from after the synch point
2025-07-02 06:41:18.364 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.364
2025-07-02 06:41:18.365 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.365 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.365
2025-07-02 06:41:18.365 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.365 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.365 alo = 387, ahi = 1101
2025-07-02 06:41:18.365 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.365 blo = 387, bhi = 1101
2025-07-02 06:41:18.365
2025-07-02 06:41:18.365     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.365         g = []
2025-07-02 06:41:18.365         if alo < ahi:
2025-07-02 06:41:18.365             if blo < bhi:
2025-07-02 06:41:18.365                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.365             else:
2025-07-02 06:41:18.365                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.365         elif blo < bhi:
2025-07-02 06:41:18.365             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.365
2025-07-02 06:41:18.366 >       yield from g
2025-07-02 06:41:18.366
2025-07-02 06:41:18.366 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.366 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.366
2025-07-02 06:41:18.366 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.366 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.366 alo = 387, ahi = 1101
2025-07-02 06:41:18.366 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.366 blo = 387, bhi = 1101
2025-07-02 06:41:18.366
2025-07-02 06:41:18.366     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.366         r"""
2025-07-02 06:41:18.366         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.366         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.366         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.366         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.366
2025-07-02 06:41:18.366         Example:
2025-07-02 06:41:18.367
2025-07-02 06:41:18.367         >>> d = Differ()
2025-07-02 06:41:18.367         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.367         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.367         >>> print(''.join(results), end="")
2025-07-02 06:41:18.367         - abcDefghiJkl
2025-07-02 06:41:18.367         + abcdefGhijkl
2025-07-02 06:41:18.367         """
2025-07-02 06:41:18.367
2025-07-02 06:41:18.367         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.367         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.367         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.367         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.367         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.367
2025-07-02 06:41:18.367         # search for the pair that matches best without being identical
2025-07-02 06:41:18.367         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.367         # on junk -- unless we have to)
2025-07-02 06:41:18.368         for j in range(blo, bhi):
2025-07-02 06:41:18.368             bj = b[j]
2025-07-02 06:41:18.368             cruncher.set_seq2(bj)
2025-07-02 06:41:18.368             for i in range(alo, ahi):
2025-07-02 06:41:18.368                 ai = a[i]
2025-07-02 06:41:18.368                 if ai == bj:
2025-07-02 06:41:18.368                     if eqi is None:
2025-07-02 06:41:18.368                         eqi, eqj = i, j
2025-07-02 06:41:18.368                     continue
2025-07-02 06:41:18.368                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.368                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.368                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.368                 # compares by a factor of 3.
2025-07-02 06:41:18.368                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.368                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.368                 # of the computation is cached by cruncher
2025-07-02 06:41:18.368                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.368                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.368                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.368                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.369         if best_ratio < cutoff:
2025-07-02 06:41:18.369             # no non-identical "pretty close" pair
2025-07-02 06:41:18.369             if eqi is None:
2025-07-02 06:41:18.369                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.369                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.369                 return
2025-07-02 06:41:18.369             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.369             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.369         else:
2025-07-02 06:41:18.369             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.369             eqi = None
2025-07-02 06:41:18.369
2025-07-02 06:41:18.369         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.369         # identical
2025-07-02 06:41:18.369
2025-07-02 06:41:18.369         # pump out diffs from before the synch point
2025-07-02 06:41:18.369         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.369
2025-07-02 06:41:18.369         # do intraline marking on the synch pair
2025-07-02 06:41:18.369         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.370         if eqi is None:
2025-07-02 06:41:18.370             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.370             atags = btags = ""
2025-07-02 06:41:18.370             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.370             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.370                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.370                 if tag == 'replace':
2025-07-02 06:41:18.370                     atags += '^' * la
2025-07-02 06:41:18.370                     btags += '^' * lb
2025-07-02 06:41:18.370                 elif tag == 'delete':
2025-07-02 06:41:18.370                     atags += '-' * la
2025-07-02 06:41:18.370                 elif tag == 'insert':
2025-07-02 06:41:18.370                     btags += '+' * lb
2025-07-02 06:41:18.370                 elif tag == 'equal':
2025-07-02 06:41:18.370                     atags += ' ' * la
2025-07-02 06:41:18.370                     btags += ' ' * lb
2025-07-02 06:41:18.370                 else:
2025-07-02 06:41:18.370                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.370             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.370         else:
2025-07-02 06:41:18.370             # the synch pair is identical
2025-07-02 06:41:18.371             yield '  ' + aelt
2025-07-02 06:41:18.371
2025-07-02 06:41:18.371         # pump out diffs from after the synch point
2025-07-02 06:41:18.371 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.371
2025-07-02 06:41:18.371 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.371 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.371
2025-07-02 06:41:18.371 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.371 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.371 alo = 388, ahi = 1101
2025-07-02 06:41:18.371 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.371 blo = 388, bhi = 1101
2025-07-02 06:41:18.371
2025-07-02 06:41:18.371     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.371         g = []
2025-07-02 06:41:18.371         if alo < ahi:
2025-07-02 06:41:18.371             if blo < bhi:
2025-07-02 06:41:18.371                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.371             else:
2025-07-02 06:41:18.372                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.372         elif blo < bhi:
2025-07-02 06:41:18.372             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.372
2025-07-02 06:41:18.372 >       yield from g
2025-07-02 06:41:18.372
2025-07-02 06:41:18.372 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.372 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.372
2025-07-02 06:41:18.372 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.372 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.372 alo = 388, ahi = 1101
2025-07-02 06:41:18.372 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.372 blo = 388, bhi = 1101
2025-07-02 06:41:18.372
2025-07-02 06:41:18.372     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.372         r"""
2025-07-02 06:41:18.372         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.372         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.372         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.373         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.373
2025-07-02 06:41:18.373         Example:
2025-07-02 06:41:18.373
2025-07-02 06:41:18.373         >>> d = Differ()
2025-07-02 06:41:18.373         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.373         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.373         >>> print(''.join(results), end="")
2025-07-02 06:41:18.373         - abcDefghiJkl
2025-07-02 06:41:18.373         + abcdefGhijkl
2025-07-02 06:41:18.373         """
2025-07-02 06:41:18.373
2025-07-02 06:41:18.373         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.373         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.373         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.374         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.374         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.374
2025-07-02 06:41:18.374         # search for the pair that matches best without being identical
2025-07-02 06:41:18.374         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.374         # on junk -- unless we have to)
2025-07-02 06:41:18.374         for j in range(blo, bhi):
2025-07-02 06:41:18.374             bj = b[j]
2025-07-02 06:41:18.374             cruncher.set_seq2(bj)
2025-07-02 06:41:18.374             for i in range(alo, ahi):
2025-07-02 06:41:18.374                 ai = a[i]
2025-07-02 06:41:18.374                 if ai == bj:
2025-07-02 06:41:18.374                     if eqi is None:
2025-07-02 06:41:18.374                         eqi, eqj = i, j
2025-07-02 06:41:18.374                     continue
2025-07-02 06:41:18.374                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.374                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.374                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.374                 # compares by a factor of 3.
2025-07-02 06:41:18.375                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.375                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.375                 # of the computation is cached by cruncher
2025-07-02 06:41:18.375                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.375                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.375                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.375                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.375         if best_ratio < cutoff:
2025-07-02 06:41:18.375             # no non-identical "pretty close" pair
2025-07-02 06:41:18.375             if eqi is None:
2025-07-02 06:41:18.375                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.375                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.375                 return
2025-07-02 06:41:18.375             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.375             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.375         else:
2025-07-02 06:41:18.375             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.375             eqi = None
2025-07-02 06:41:18.375
2025-07-02 06:41:18.375         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.376         # identical
2025-07-02 06:41:18.376
2025-07-02 06:41:18.376         # pump out diffs from before the synch point
2025-07-02 06:41:18.376         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.376
2025-07-02 06:41:18.376         # do intraline marking on the synch pair
2025-07-02 06:41:18.376         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.376         if eqi is None:
2025-07-02 06:41:18.376             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.376             atags = btags = ""
2025-07-02 06:41:18.376             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.376             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.376                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.376                 if tag == 'replace':
2025-07-02 06:41:18.376                     atags += '^' * la
2025-07-02 06:41:18.376                     btags += '^' * lb
2025-07-02 06:41:18.376                 elif tag == 'delete':
2025-07-02 06:41:18.376                     atags += '-' * la
2025-07-02 06:41:18.376                 elif tag == 'insert':
2025-07-02 06:41:18.376                     btags += '+' * lb
2025-07-02 06:41:18.377                 elif tag == 'equal':
2025-07-02 06:41:18.377                     atags += ' ' * la
2025-07-02 06:41:18.377                     btags += ' ' * lb
2025-07-02 06:41:18.377                 else:
2025-07-02 06:41:18.377                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.377             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.377         else:
2025-07-02 06:41:18.377             # the synch pair is identical
2025-07-02 06:41:18.377             yield '  ' + aelt
2025-07-02 06:41:18.377
2025-07-02 06:41:18.377         # pump out diffs from after the synch point
2025-07-02 06:41:18.377 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.377
2025-07-02 06:41:18.377 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.377 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.377
2025-07-02 06:41:18.377 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.377 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.377 alo = 389, ahi = 1101
2025-07-02 06:41:18.377 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.378 blo = 389, bhi = 1101
2025-07-02 06:41:18.378
2025-07-02 06:41:18.378     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.378         g = []
2025-07-02 06:41:18.378         if alo < ahi:
2025-07-02 06:41:18.378             if blo < bhi:
2025-07-02 06:41:18.378                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.378             else:
2025-07-02 06:41:18.378                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.378         elif blo < bhi:
2025-07-02 06:41:18.378             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.378
2025-07-02 06:41:18.378 >       yield from g
2025-07-02 06:41:18.378
2025-07-02 06:41:18.378 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.378 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.378
2025-07-02 06:41:18.378 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.378 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.378 alo = 389, ahi = 1101
2025-07-02 06:41:18.378 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.379 blo = 389, bhi = 1101
2025-07-02 06:41:18.379
2025-07-02 06:41:18.379     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.379         r"""
2025-07-02 06:41:18.379         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.379         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.379         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.379         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.379
2025-07-02 06:41:18.379         Example:
2025-07-02 06:41:18.379
2025-07-02 06:41:18.379         >>> d = Differ()
2025-07-02 06:41:18.379         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.379         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.379         >>> print(''.join(results), end="")
2025-07-02 06:41:18.379         - abcDefghiJkl
2025-07-02 06:41:18.379         + abcdefGhijkl
2025-07-02 06:41:18.379         """
2025-07-02 06:41:18.380
2025-07-02 06:41:18.380         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.380         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.380         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.380         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.380         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.380
2025-07-02 06:41:18.380         # search for the pair that matches best without being identical
2025-07-02 06:41:18.380         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.380         # on junk -- unless we have to)
2025-07-02 06:41:18.380         for j in range(blo, bhi):
2025-07-02 06:41:18.380             bj = b[j]
2025-07-02 06:41:18.380             cruncher.set_seq2(bj)
2025-07-02 06:41:18.380             for i in range(alo, ahi):
2025-07-02 06:41:18.380                 ai = a[i]
2025-07-02 06:41:18.380                 if ai == bj:
2025-07-02 06:41:18.380                     if eqi is None:
2025-07-02 06:41:18.380                         eqi, eqj = i, j
2025-07-02 06:41:18.380                     continue
2025-07-02 06:41:18.380                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.381                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.381                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.381                 # compares by a factor of 3.
2025-07-02 06:41:18.381                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.381                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.381                 # of the computation is cached by cruncher
2025-07-02 06:41:18.381                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.381                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.381                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.381                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.381         if best_ratio < cutoff:
2025-07-02 06:41:18.381             # no non-identical "pretty close" pair
2025-07-02 06:41:18.381             if eqi is None:
2025-07-02 06:41:18.381                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.381                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.381                 return
2025-07-02 06:41:18.381             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.381             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.381         else:
2025-07-02 06:41:18.381             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.382             eqi = None
2025-07-02 06:41:18.382
2025-07-02 06:41:18.382         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.382         # identical
2025-07-02 06:41:18.382
2025-07-02 06:41:18.382         # pump out diffs from before the synch point
2025-07-02 06:41:18.382         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.382
2025-07-02 06:41:18.382         # do intraline marking on the synch pair
2025-07-02 06:41:18.382         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.382         if eqi is None:
2025-07-02 06:41:18.382             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.382             atags = btags = ""
2025-07-02 06:41:18.382             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.382             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.382                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.382                 if tag == 'replace':
2025-07-02 06:41:18.382                     atags += '^' * la
2025-07-02 06:41:18.382                     btags += '^' * lb
2025-07-02 06:41:18.383                 elif tag == 'delete':
2025-07-02 06:41:18.383                     atags += '-' * la
2025-07-02 06:41:18.383                 elif tag == 'insert':
2025-07-02 06:41:18.383                     btags += '+' * lb
2025-07-02 06:41:18.383                 elif tag == 'equal':
2025-07-02 06:41:18.383                     atags += ' ' * la
2025-07-02 06:41:18.383                     btags += ' ' * lb
2025-07-02 06:41:18.383                 else:
2025-07-02 06:41:18.383                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.383             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.383         else:
2025-07-02 06:41:18.383             # the synch pair is identical
2025-07-02 06:41:18.383             yield '  ' + aelt
2025-07-02 06:41:18.383
2025-07-02 06:41:18.383         # pump out diffs from after the synch point
2025-07-02 06:41:18.383 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.383
2025-07-02 06:41:18.383 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.383 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.384
2025-07-02 06:41:18.384 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.384 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.384 alo = 390, ahi = 1101
2025-07-02 06:41:18.384 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.384 blo = 390, bhi = 1101
2025-07-02 06:41:18.384
2025-07-02 06:41:18.384     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.384         g = []
2025-07-02 06:41:18.384         if alo < ahi:
2025-07-02 06:41:18.384             if blo < bhi:
2025-07-02 06:41:18.384                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.384             else:
2025-07-02 06:41:18.384                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.384         elif blo < bhi:
2025-07-02 06:41:18.384             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.384
2025-07-02 06:41:18.384 >       yield from g
2025-07-02 06:41:18.384
2025-07-02 06:41:18.384 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.385 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.385
2025-07-02 06:41:18.385 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.385 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.385 alo = 390, ahi = 1101
2025-07-02 06:41:18.385 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.385 blo = 390, bhi = 1101
2025-07-02 06:41:18.385
2025-07-02 06:41:18.385     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.385         r"""
2025-07-02 06:41:18.385         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.385         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.385         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.385         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.385
2025-07-02 06:41:18.385         Example:
2025-07-02 06:41:18.385
2025-07-02 06:41:18.385         >>> d = Differ()
2025-07-02 06:41:18.385         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.385         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.386         >>> print(''.join(results), end="")
2025-07-02 06:41:18.386         - abcDefghiJkl
2025-07-02 06:41:18.386         + abcdefGhijkl
2025-07-02 06:41:18.386         """
2025-07-02 06:41:18.386
2025-07-02 06:41:18.386         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.386         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.386         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.386         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.386         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.386
2025-07-02 06:41:18.386         # search for the pair that matches best without being identical
2025-07-02 06:41:18.386         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.386         # on junk -- unless we have to)
2025-07-02 06:41:18.386         for j in range(blo, bhi):
2025-07-02 06:41:18.386             bj = b[j]
2025-07-02 06:41:18.386             cruncher.set_seq2(bj)
2025-07-02 06:41:18.386             for i in range(alo, ahi):
2025-07-02 06:41:18.386                 ai = a[i]
2025-07-02 06:41:18.387                 if ai == bj:
2025-07-02 06:41:18.387                     if eqi is None:
2025-07-02 06:41:18.387                         eqi, eqj = i, j
2025-07-02 06:41:18.387                     continue
2025-07-02 06:41:18.387                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.387                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.387                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.387                 # compares by a factor of 3.
2025-07-02 06:41:18.387                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.387                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.387                 # of the computation is cached by cruncher
2025-07-02 06:41:18.387                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.387                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.387                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.387                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.387         if best_ratio < cutoff:
2025-07-02 06:41:18.387             # no non-identical "pretty close" pair
2025-07-02 06:41:18.387             if eqi is None:
2025-07-02 06:41:18.387                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.387                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.388                 return
2025-07-02 06:41:18.388             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.388             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.388         else:
2025-07-02 06:41:18.388             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.388             eqi = None
2025-07-02 06:41:18.388
2025-07-02 06:41:18.388         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.388         # identical
2025-07-02 06:41:18.388
2025-07-02 06:41:18.388         # pump out diffs from before the synch point
2025-07-02 06:41:18.388         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.388
2025-07-02 06:41:18.388         # do intraline marking on the synch pair
2025-07-02 06:41:18.388         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.388         if eqi is None:
2025-07-02 06:41:18.388             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.388             atags = btags = ""
2025-07-02 06:41:18.388             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.389             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.389                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.389                 if tag == 'replace':
2025-07-02 06:41:18.389                     atags += '^' * la
2025-07-02 06:41:18.389                     btags += '^' * lb
2025-07-02 06:41:18.389                 elif tag == 'delete':
2025-07-02 06:41:18.389                     atags += '-' * la
2025-07-02 06:41:18.389                 elif tag == 'insert':
2025-07-02 06:41:18.389                     btags += '+' * lb
2025-07-02 06:41:18.389                 elif tag == 'equal':
2025-07-02 06:41:18.389                     atags += ' ' * la
2025-07-02 06:41:18.389                     btags += ' ' * lb
2025-07-02 06:41:18.389                 else:
2025-07-02 06:41:18.389                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.389             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.389         else:
2025-07-02 06:41:18.389             # the synch pair is identical
2025-07-02 06:41:18.389             yield '  ' + aelt
2025-07-02 06:41:18.390
2025-07-02 06:41:18.390         # pump out diffs from after the synch point
2025-07-02 06:41:18.390 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.390
2025-07-02 06:41:18.390 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.390 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.390
2025-07-02 06:41:18.390 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.390 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.390 alo = 391, ahi = 1101
2025-07-02 06:41:18.390 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.390 blo = 391, bhi = 1101
2025-07-02 06:41:18.390
2025-07-02 06:41:18.390     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.390         g = []
2025-07-02 06:41:18.390         if alo < ahi:
2025-07-02 06:41:18.390             if blo < bhi:
2025-07-02 06:41:18.390                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.391             else:
2025-07-02 06:41:18.391                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.391         elif blo < bhi:
2025-07-02 06:41:18.391             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.391
2025-07-02 06:41:18.391 >       yield from g
2025-07-02 06:41:18.391
2025-07-02 06:41:18.391 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.391 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.391
2025-07-02 06:41:18.391 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.391 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.391 alo = 391, ahi = 1101
2025-07-02 06:41:18.391 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.391 blo = 391, bhi = 1101
2025-07-02 06:41:18.391
2025-07-02 06:41:18.391     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.391         r"""
2025-07-02 06:41:18.391         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.392         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.392         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.392         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.392
2025-07-02 06:41:18.392         Example:
2025-07-02 06:41:18.392
2025-07-02 06:41:18.392         >>> d = Differ()
2025-07-02 06:41:18.392         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.392         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.392         >>> print(''.join(results), end="")
2025-07-02 06:41:18.392         - abcDefghiJkl
2025-07-02 06:41:18.392         + abcdefGhijkl
2025-07-02 06:41:18.392         """
2025-07-02 06:41:18.392
2025-07-02 06:41:18.392         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.392         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.392         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.393         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.393         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.393
2025-07-02 06:41:18.393         # search for the pair that matches best without being identical
2025-07-02 06:41:18.393         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.393         # on junk -- unless we have to)
2025-07-02 06:41:18.393         for j in range(blo, bhi):
2025-07-02 06:41:18.393             bj = b[j]
2025-07-02 06:41:18.393             cruncher.set_seq2(bj)
2025-07-02 06:41:18.393             for i in range(alo, ahi):
2025-07-02 06:41:18.393                 ai = a[i]
2025-07-02 06:41:18.393                 if ai == bj:
2025-07-02 06:41:18.393                     if eqi is None:
2025-07-02 06:41:18.393                         eqi, eqj = i, j
2025-07-02 06:41:18.393                     continue
2025-07-02 06:41:18.393                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.393                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.393                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.393                 # compares by a factor of 3.
2025-07-02 06:41:18.394                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.394                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.394                 # of the computation is cached by cruncher
2025-07-02 06:41:18.394                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.394                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.394                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.394                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.394         if best_ratio < cutoff:
2025-07-02 06:41:18.394             # no non-identical "pretty close" pair
2025-07-02 06:41:18.394             if eqi is None:
2025-07-02 06:41:18.394                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.394                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.394                 return
2025-07-02 06:41:18.394             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.394             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.394         else:
2025-07-02 06:41:18.394             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.394             eqi = None
2025-07-02 06:41:18.394
2025-07-02 06:41:18.394         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.395         # identical
2025-07-02 06:41:18.395
2025-07-02 06:41:18.395         # pump out diffs from before the synch point
2025-07-02 06:41:18.395         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.395
2025-07-02 06:41:18.395         # do intraline marking on the synch pair
2025-07-02 06:41:18.395         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.395         if eqi is None:
2025-07-02 06:41:18.395             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.395             atags = btags = ""
2025-07-02 06:41:18.395             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.395             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.395                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.395                 if tag == 'replace':
2025-07-02 06:41:18.395                     atags += '^' * la
2025-07-02 06:41:18.395                     btags += '^' * lb
2025-07-02 06:41:18.395                 elif tag == 'delete':
2025-07-02 06:41:18.395                     atags += '-' * la
2025-07-02 06:41:18.395                 elif tag == 'insert':
2025-07-02 06:41:18.395                     btags += '+' * lb
2025-07-02 06:41:18.395                 elif tag == 'equal':
2025-07-02 06:41:18.396                     atags += ' ' * la
2025-07-02 06:41:18.396                     btags += ' ' * lb
2025-07-02 06:41:18.396                 else:
2025-07-02 06:41:18.396                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.396             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.396         else:
2025-07-02 06:41:18.396             # the synch pair is identical
2025-07-02 06:41:18.396             yield '  ' + aelt
2025-07-02 06:41:18.396
2025-07-02 06:41:18.396         # pump out diffs from after the synch point
2025-07-02 06:41:18.396 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.396
2025-07-02 06:41:18.396 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.396 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.396
2025-07-02 06:41:18.396 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.396 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.396 alo = 392, ahi = 1101
2025-07-02 06:41:18.396 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.397 blo = 392, bhi = 1101
2025-07-02 06:41:18.397
2025-07-02 06:41:18.397     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.397         g = []
2025-07-02 06:41:18.397         if alo < ahi:
2025-07-02 06:41:18.397             if blo < bhi:
2025-07-02 06:41:18.397                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.397             else:
2025-07-02 06:41:18.397                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.397         elif blo < bhi:
2025-07-02 06:41:18.397             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.397
2025-07-02 06:41:18.397 >       yield from g
2025-07-02 06:41:18.397
2025-07-02 06:41:18.397 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.397 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.397
2025-07-02 06:41:18.397 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.397 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.397 alo = 392, ahi = 1101
2025-07-02 06:41:18.397 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.398 blo = 392, bhi = 1101
2025-07-02 06:41:18.398
2025-07-02 06:41:18.398     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.398         r"""
2025-07-02 06:41:18.398         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.398         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.398         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.398         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.398
2025-07-02 06:41:18.398         Example:
2025-07-02 06:41:18.398
2025-07-02 06:41:18.398         >>> d = Differ()
2025-07-02 06:41:18.398         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.398         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.398         >>> print(''.join(results), end="")
2025-07-02 06:41:18.398         - abcDefghiJkl
2025-07-02 06:41:18.398         + abcdefGhijkl
2025-07-02 06:41:18.398         """
2025-07-02 06:41:18.399
2025-07-02 06:41:18.399         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.399         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.399         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.399         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.399         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.399
2025-07-02 06:41:18.399         # search for the pair that matches best without being identical
2025-07-02 06:41:18.399         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.399         # on junk -- unless we have to)
2025-07-02 06:41:18.399         for j in range(blo, bhi):
2025-07-02 06:41:18.399             bj = b[j]
2025-07-02 06:41:18.399             cruncher.set_seq2(bj)
2025-07-02 06:41:18.399             for i in range(alo, ahi):
2025-07-02 06:41:18.399                 ai = a[i]
2025-07-02 06:41:18.399                 if ai == bj:
2025-07-02 06:41:18.399                     if eqi is None:
2025-07-02 06:41:18.399                         eqi, eqj = i, j
2025-07-02 06:41:18.400                     continue
2025-07-02 06:41:18.400                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.400                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.400                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.400                 # compares by a factor of 3.
2025-07-02 06:41:18.400                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.400                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.400                 # of the computation is cached by cruncher
2025-07-02 06:41:18.400                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.400                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.400                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.400                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.400         if best_ratio < cutoff:
2025-07-02 06:41:18.400             # no non-identical "pretty close" pair
2025-07-02 06:41:18.400             if eqi is None:
2025-07-02 06:41:18.400                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.400                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.400                 return
2025-07-02 06:41:18.400             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.400             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.401         else:
2025-07-02 06:41:18.401             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.401             eqi = None
2025-07-02 06:41:18.401
2025-07-02 06:41:18.401         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.401         # identical
2025-07-02 06:41:18.401
2025-07-02 06:41:18.401         # pump out diffs from before the synch point
2025-07-02 06:41:18.401         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.401
2025-07-02 06:41:18.401         # do intraline marking on the synch pair
2025-07-02 06:41:18.401         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.401         if eqi is None:
2025-07-02 06:41:18.401             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.401             atags = btags = ""
2025-07-02 06:41:18.401             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.401             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.401                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.401                 if tag == 'replace':
2025-07-02 06:41:18.402                     atags += '^' * la
2025-07-02 06:41:18.402                     btags += '^' * lb
2025-07-02 06:41:18.402                 elif tag == 'delete':
2025-07-02 06:41:18.402                     atags += '-' * la
2025-07-02 06:41:18.402                 elif tag == 'insert':
2025-07-02 06:41:18.402                     btags += '+' * lb
2025-07-02 06:41:18.402                 elif tag == 'equal':
2025-07-02 06:41:18.402                     atags += ' ' * la
2025-07-02 06:41:18.402                     btags += ' ' * lb
2025-07-02 06:41:18.402                 else:
2025-07-02 06:41:18.402                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.402             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.402         else:
2025-07-02 06:41:18.402             # the synch pair is identical
2025-07-02 06:41:18.402             yield '  ' + aelt
2025-07-02 06:41:18.402
2025-07-02 06:41:18.402         # pump out diffs from after the synch point
2025-07-02 06:41:18.402 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.402
2025-07-02 06:41:18.402 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.403 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.403
2025-07-02 06:41:18.403 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.403 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.403 alo = 393, ahi = 1101
2025-07-02 06:41:18.403 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.403 blo = 393, bhi = 1101
2025-07-02 06:41:18.403
2025-07-02 06:41:18.403     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.403         g = []
2025-07-02 06:41:18.403         if alo < ahi:
2025-07-02 06:41:18.403             if blo < bhi:
2025-07-02 06:41:18.403                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.403             else:
2025-07-02 06:41:18.403                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.403         elif blo < bhi:
2025-07-02 06:41:18.403             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.403
2025-07-02 06:41:18.403 >       yield from g
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.404 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.404 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.404 alo = 393, ahi = 1101
2025-07-02 06:41:18.404 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.404 blo = 393, bhi = 1101
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.404         r"""
2025-07-02 06:41:18.404         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.404         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.404         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.404         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404         Example:
2025-07-02 06:41:18.404
2025-07-02 06:41:18.404         >>> d = Differ()
2025-07-02 06:41:18.405         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.405         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.405         >>> print(''.join(results), end="")
2025-07-02 06:41:18.405         - abcDefghiJkl
2025-07-02 06:41:18.405         + abcdefGhijkl
2025-07-02 06:41:18.405         """
2025-07-02 06:41:18.405
2025-07-02 06:41:18.405         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.405         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.405         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.405         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.405         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.405
2025-07-02 06:41:18.405         # search for the pair that matches best without being identical
2025-07-02 06:41:18.405         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.405         # on junk -- unless we have to)
2025-07-02 06:41:18.405         for j in range(blo, bhi):
2025-07-02 06:41:18.406             bj = b[j]
2025-07-02 06:41:18.406             cruncher.set_seq2(bj)
2025-07-02 06:41:18.406             for i in range(alo, ahi):
2025-07-02 06:41:18.406                 ai = a[i]
2025-07-02 06:41:18.406                 if ai == bj:
2025-07-02 06:41:18.406                     if eqi is None:
2025-07-02 06:41:18.406                         eqi, eqj = i, j
2025-07-02 06:41:18.406                     continue
2025-07-02 06:41:18.406                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.406                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.406                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.406                 # compares by a factor of 3.
2025-07-02 06:41:18.406                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.406                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.406                 # of the computation is cached by cruncher
2025-07-02 06:41:18.406                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.406                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.406                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.406                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.407         if best_ratio < cutoff:
2025-07-02 06:41:18.407             # no non-identical "pretty close" pair
2025-07-02 06:41:18.407             if eqi is None:
2025-07-02 06:41:18.407                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.407                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.407                 return
2025-07-02 06:41:18.407             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.407             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.407         else:
2025-07-02 06:41:18.407             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.407             eqi = None
2025-07-02 06:41:18.407
2025-07-02 06:41:18.407         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.407         # identical
2025-07-02 06:41:18.407
2025-07-02 06:41:18.407         # pump out diffs from before the synch point
2025-07-02 06:41:18.407         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.407
2025-07-02 06:41:18.407         # do intraline marking on the synch pair
2025-07-02 06:41:18.407         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.407         if eqi is None:
2025-07-02 06:41:18.408             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.408             atags = btags = ""
2025-07-02 06:41:18.408             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.408             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.408                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.408                 if tag == 'replace':
2025-07-02 06:41:18.408                     atags += '^' * la
2025-07-02 06:41:18.408                     btags += '^' * lb
2025-07-02 06:41:18.408                 elif tag == 'delete':
2025-07-02 06:41:18.408                     atags += '-' * la
2025-07-02 06:41:18.408                 elif tag == 'insert':
2025-07-02 06:41:18.408                     btags += '+' * lb
2025-07-02 06:41:18.408                 elif tag == 'equal':
2025-07-02 06:41:18.408                     atags += ' ' * la
2025-07-02 06:41:18.408                     btags += ' ' * lb
2025-07-02 06:41:18.408                 else:
2025-07-02 06:41:18.408                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.408             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.409         else:
2025-07-02 06:41:18.409             # the synch pair is identical
2025-07-02 06:41:18.409             yield '  ' + aelt
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409         # pump out diffs from after the synch point
2025-07-02 06:41:18.409 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.409 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.409 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.409 alo = 394, ahi = 1101
2025-07-02 06:41:18.409 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.409 blo = 394, bhi = 1101
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.409         g = []
2025-07-02 06:41:18.409         if alo < ahi:
2025-07-02 06:41:18.409             if blo < bhi:
2025-07-02 06:41:18.409                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.409             else:
2025-07-02 06:41:18.409                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.409         elif blo < bhi:
2025-07-02 06:41:18.409             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.409
2025-07-02 06:41:18.409 >       yield from g
2025-07-02 06:41:18.410
2025-07-02 06:41:18.410 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.410 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.410
2025-07-02 06:41:18.410 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.410 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.410 alo = 394, ahi = 1101
2025-07-02 06:41:18.410 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.410 blo = 394, bhi = 1101
2025-07-02 06:41:18.410
2025-07-02 06:41:18.410     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.410         r"""
2025-07-02 06:41:18.410         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.410         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.410         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.410         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.410
2025-07-02 06:41:18.410         Example:
2025-07-02 06:41:18.410
2025-07-02 06:41:18.411         >>> d = Differ()
2025-07-02 06:41:18.411         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.411         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.411         >>> print(''.join(results), end="")
2025-07-02 06:41:18.411         - abcDefghiJkl
2025-07-02 06:41:18.411         + abcdefGhijkl
2025-07-02 06:41:18.411         """
2025-07-02 06:41:18.411
2025-07-02 06:41:18.411         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.411         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.411         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.411         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.411         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.411
2025-07-02 06:41:18.411         # search for the pair that matches best without being identical
2025-07-02 06:41:18.411         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.411         # on junk -- unless we have to)
2025-07-02 06:41:18.411         for j in range(blo, bhi):
2025-07-02 06:41:18.412             bj = b[j]
2025-07-02 06:41:18.412             cruncher.set_seq2(bj)
2025-07-02 06:41:18.412             for i in range(alo, ahi):
2025-07-02 06:41:18.412                 ai = a[i]
2025-07-02 06:41:18.412                 if ai == bj:
2025-07-02 06:41:18.412                     if eqi is None:
2025-07-02 06:41:18.412                         eqi, eqj = i, j
2025-07-02 06:41:18.412                     continue
2025-07-02 06:41:18.412                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.412                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.412                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.412                 # compares by a factor of 3.
2025-07-02 06:41:18.412                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.412                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.412                 # of the computation is cached by cruncher
2025-07-02 06:41:18.412                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.412                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.412                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.412                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.412         if best_ratio < cutoff:
2025-07-02 06:41:18.413             # no non-identical "pretty close" pair
2025-07-02 06:41:18.413             if eqi is None:
2025-07-02 06:41:18.413                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.413                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.413                 return
2025-07-02 06:41:18.413             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.413             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.413         else:
2025-07-02 06:41:18.413             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.413             eqi = None
2025-07-02 06:41:18.413
2025-07-02 06:41:18.413         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.413         # identical
2025-07-02 06:41:18.413
2025-07-02 06:41:18.413         # pump out diffs from before the synch point
2025-07-02 06:41:18.413         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.413
2025-07-02 06:41:18.413         # do intraline marking on the synch pair
2025-07-02 06:41:18.413         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.414         if eqi is None:
2025-07-02 06:41:18.414             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.414             atags = btags = ""
2025-07-02 06:41:18.414             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.414             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.414                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.414                 if tag == 'replace':
2025-07-02 06:41:18.414                     atags += '^' * la
2025-07-02 06:41:18.414                     btags += '^' * lb
2025-07-02 06:41:18.414                 elif tag == 'delete':
2025-07-02 06:41:18.414                     atags += '-' * la
2025-07-02 06:41:18.414                 elif tag == 'insert':
2025-07-02 06:41:18.414                     btags += '+' * lb
2025-07-02 06:41:18.414                 elif tag == 'equal':
2025-07-02 06:41:18.414                     atags += ' ' * la
2025-07-02 06:41:18.414                     btags += ' ' * lb
2025-07-02 06:41:18.414                 else:
2025-07-02 06:41:18.414                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.414             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.414         else:
2025-07-02 06:41:18.415             # the synch pair is identical
2025-07-02 06:41:18.415             yield '  ' + aelt
2025-07-02 06:41:18.415
2025-07-02 06:41:18.415         # pump out diffs from after the synch point
2025-07-02 06:41:18.415 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.415
2025-07-02 06:41:18.415 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.415 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.415
2025-07-02 06:41:18.415 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.415 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.415 alo = 395, ahi = 1101
2025-07-02 06:41:18.415 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.415 blo = 395, bhi = 1101
2025-07-02 06:41:18.415
2025-07-02 06:41:18.415     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.415         g = []
2025-07-02 06:41:18.415         if alo < ahi:
2025-07-02 06:41:18.415             if blo < bhi:
2025-07-02 06:41:18.415                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.416             else:
2025-07-02 06:41:18.416                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.416         elif blo < bhi:
2025-07-02 06:41:18.416             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.416
2025-07-02 06:41:18.416 >       yield from g
2025-07-02 06:41:18.416
2025-07-02 06:41:18.416 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.416 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.416
2025-07-02 06:41:18.416 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.416 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.416 alo = 395, ahi = 1101
2025-07-02 06:41:18.416 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.416 blo = 395, bhi = 1101
2025-07-02 06:41:18.416
2025-07-02 06:41:18.416     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.416         r"""
2025-07-02 06:41:18.417         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.417         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.417         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.417         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.417
2025-07-02 06:41:18.417         Example:
2025-07-02 06:41:18.417
2025-07-02 06:41:18.417         >>> d = Differ()
2025-07-02 06:41:18.417         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.417         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.417         >>> print(''.join(results), end="")
2025-07-02 06:41:18.417         - abcDefghiJkl
2025-07-02 06:41:18.417         + abcdefGhijkl
2025-07-02 06:41:18.417         """
2025-07-02 06:41:18.417
2025-07-02 06:41:18.417         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.417         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.418         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.418         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.418         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.418
2025-07-02 06:41:18.418         # search for the pair that matches best without being identical
2025-07-02 06:41:18.418         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.418         # on junk -- unless we have to)
2025-07-02 06:41:18.418         for j in range(blo, bhi):
2025-07-02 06:41:18.418             bj = b[j]
2025-07-02 06:41:18.418             cruncher.set_seq2(bj)
2025-07-02 06:41:18.418             for i in range(alo, ahi):
2025-07-02 06:41:18.418                 ai = a[i]
2025-07-02 06:41:18.418                 if ai == bj:
2025-07-02 06:41:18.418                     if eqi is None:
2025-07-02 06:41:18.418                         eqi, eqj = i, j
2025-07-02 06:41:18.418                     continue
2025-07-02 06:41:18.418                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.418                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.418                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.418                 # compares by a factor of 3.
2025-07-02 06:41:18.419                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.419                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.419                 # of the computation is cached by cruncher
2025-07-02 06:41:18.419                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.419                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.419                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.419                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.419         if best_ratio < cutoff:
2025-07-02 06:41:18.419             # no non-identical "pretty close" pair
2025-07-02 06:41:18.419             if eqi is None:
2025-07-02 06:41:18.419                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.419                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.419                 return
2025-07-02 06:41:18.419             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.419             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.419         else:
2025-07-02 06:41:18.419             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.419             eqi = None
2025-07-02 06:41:18.420
2025-07-02 06:41:18.420         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.420         # identical
2025-07-02 06:41:18.420
2025-07-02 06:41:18.420         # pump out diffs from before the synch point
2025-07-02 06:41:18.420         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.420
2025-07-02 06:41:18.420         # do intraline marking on the synch pair
2025-07-02 06:41:18.420         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.420         if eqi is None:
2025-07-02 06:41:18.420             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.420             atags = btags = ""
2025-07-02 06:41:18.420             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.420             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.420                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.420                 if tag == 'replace':
2025-07-02 06:41:18.420                     atags += '^' * la
2025-07-02 06:41:18.420                     btags += '^' * lb
2025-07-02 06:41:18.421                 elif tag == 'delete':
2025-07-02 06:41:18.421                     atags += '-' * la
2025-07-02 06:41:18.421                 elif tag == 'insert':
2025-07-02 06:41:18.421                     btags += '+' * lb
2025-07-02 06:41:18.421                 elif tag == 'equal':
2025-07-02 06:41:18.421                     atags += ' ' * la
2025-07-02 06:41:18.421                     btags += ' ' * lb
2025-07-02 06:41:18.421                 else:
2025-07-02 06:41:18.421                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.421             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.421         else:
2025-07-02 06:41:18.421             # the synch pair is identical
2025-07-02 06:41:18.421             yield '  ' + aelt
2025-07-02 06:41:18.421
2025-07-02 06:41:18.421         # pump out diffs from after the synch point
2025-07-02 06:41:18.421 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.421
2025-07-02 06:41:18.421 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.421 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.421
2025-07-02 06:41:18.422 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.422 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.422 alo = 396, ahi = 1101
2025-07-02 06:41:18.422 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.422 blo = 396, bhi = 1101
2025-07-02 06:41:18.422
2025-07-02 06:41:18.422     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.422         g = []
2025-07-02 06:41:18.422         if alo < ahi:
2025-07-02 06:41:18.422             if blo < bhi:
2025-07-02 06:41:18.422                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.422             else:
2025-07-02 06:41:18.422                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.422         elif blo < bhi:
2025-07-02 06:41:18.422             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.422
2025-07-02 06:41:18.422 >       yield from g
2025-07-02 06:41:18.422
2025-07-02 06:41:18.422 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.422 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.423
2025-07-02 06:41:18.423 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.423 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.423 alo = 396, ahi = 1101
2025-07-02 06:41:18.423 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.423 blo = 396, bhi = 1101
2025-07-02 06:41:18.423
2025-07-02 06:41:18.423     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.423         r"""
2025-07-02 06:41:18.423         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.423         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.423         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.423         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.423
2025-07-02 06:41:18.423         Example:
2025-07-02 06:41:18.423
2025-07-02 06:41:18.423         >>> d = Differ()
2025-07-02 06:41:18.423         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.423         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.424         >>> print(''.join(results), end="")
2025-07-02 06:41:18.424         - abcDefghiJkl
2025-07-02 06:41:18.424         + abcdefGhijkl
2025-07-02 06:41:18.424         """
2025-07-02 06:41:18.424
2025-07-02 06:41:18.424         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.424         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.424         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.424         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.424         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.424
2025-07-02 06:41:18.424         # search for the pair that matches best without being identical
2025-07-02 06:41:18.424         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.424         # on junk -- unless we have to)
2025-07-02 06:41:18.424         for j in range(blo, bhi):
2025-07-02 06:41:18.424             bj = b[j]
2025-07-02 06:41:18.424             cruncher.set_seq2(bj)
2025-07-02 06:41:18.424             for i in range(alo, ahi):
2025-07-02 06:41:18.425                 ai = a[i]
2025-07-02 06:41:18.425                 if ai == bj:
2025-07-02 06:41:18.425                     if eqi is None:
2025-07-02 06:41:18.425                         eqi, eqj = i, j
2025-07-02 06:41:18.425                     continue
2025-07-02 06:41:18.425                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.425                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.425                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.425                 # compares by a factor of 3.
2025-07-02 06:41:18.425                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.425                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.425                 # of the computation is cached by cruncher
2025-07-02 06:41:18.425                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.425                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.425                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.425                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.425         if best_ratio < cutoff:
2025-07-02 06:41:18.425             # no non-identical "pretty close" pair
2025-07-02 06:41:18.425             if eqi is None:
2025-07-02 06:41:18.426                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.426                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.426                 return
2025-07-02 06:41:18.426             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.426             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.426         else:
2025-07-02 06:41:18.426             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.426             eqi = None
2025-07-02 06:41:18.426
2025-07-02 06:41:18.426         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.426         # identical
2025-07-02 06:41:18.426
2025-07-02 06:41:18.426         # pump out diffs from before the synch point
2025-07-02 06:41:18.426         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.426
2025-07-02 06:41:18.426         # do intraline marking on the synch pair
2025-07-02 06:41:18.426         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.426         if eqi is None:
2025-07-02 06:41:18.427             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.427             atags = btags = ""
2025-07-02 06:41:18.427             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.427             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.427                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.427                 if tag == 'replace':
2025-07-02 06:41:18.427                     atags += '^' * la
2025-07-02 06:41:18.427                     btags += '^' * lb
2025-07-02 06:41:18.427                 elif tag == 'delete':
2025-07-02 06:41:18.427                     atags += '-' * la
2025-07-02 06:41:18.427                 elif tag == 'insert':
2025-07-02 06:41:18.427                     btags += '+' * lb
2025-07-02 06:41:18.427                 elif tag == 'equal':
2025-07-02 06:41:18.427                     atags += ' ' * la
2025-07-02 06:41:18.427                     btags += ' ' * lb
2025-07-02 06:41:18.427                 else:
2025-07-02 06:41:18.427                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.427             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.427         else:
2025-07-02 06:41:18.427             # the synch pair is identical
2025-07-02 06:41:18.428             yield '  ' + aelt
2025-07-02 06:41:18.428
2025-07-02 06:41:18.428         # pump out diffs from after the synch point
2025-07-02 06:41:18.428 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.428
2025-07-02 06:41:18.428 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.428 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.428
2025-07-02 06:41:18.428 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.428 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.428 alo = 397, ahi = 1101
2025-07-02 06:41:18.428 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.428 blo = 397, bhi = 1101
2025-07-02 06:41:18.428
2025-07-02 06:41:18.428     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.428         g = []
2025-07-02 06:41:18.428         if alo < ahi:
2025-07-02 06:41:18.428             if blo < bhi:
2025-07-02 06:41:18.428                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.428             else:
2025-07-02 06:41:18.429                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.429         elif blo < bhi:
2025-07-02 06:41:18.429             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.429
2025-07-02 06:41:18.429 >       yield from g
2025-07-02 06:41:18.429
2025-07-02 06:41:18.429 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.429 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.429
2025-07-02 06:41:18.429 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.429 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.429 alo = 397, ahi = 1101
2025-07-02 06:41:18.429 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.429 blo = 397, bhi = 1101
2025-07-02 06:41:18.429
2025-07-02 06:41:18.429     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.429         r"""
2025-07-02 06:41:18.429         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.429         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.429         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.430         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.430
2025-07-02 06:41:18.430         Example:
2025-07-02 06:41:18.430
2025-07-02 06:41:18.430         >>> d = Differ()
2025-07-02 06:41:18.430         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.430         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.430         >>> print(''.join(results), end="")
2025-07-02 06:41:18.430         - abcDefghiJkl
2025-07-02 06:41:18.430         + abcdefGhijkl
2025-07-02 06:41:18.430         """
2025-07-02 06:41:18.430
2025-07-02 06:41:18.430         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.430         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.430         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.430         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.430         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.430
2025-07-02 06:41:18.430         # search for the pair that matches best without being identical
2025-07-02 06:41:18.431         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.431         # on junk -- unless we have to)
2025-07-02 06:41:18.431         for j in range(blo, bhi):
2025-07-02 06:41:18.431             bj = b[j]
2025-07-02 06:41:18.431             cruncher.set_seq2(bj)
2025-07-02 06:41:18.431             for i in range(alo, ahi):
2025-07-02 06:41:18.431                 ai = a[i]
2025-07-02 06:41:18.431                 if ai == bj:
2025-07-02 06:41:18.431                     if eqi is None:
2025-07-02 06:41:18.431                         eqi, eqj = i, j
2025-07-02 06:41:18.431                     continue
2025-07-02 06:41:18.431                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.431                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.431                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.431                 # compares by a factor of 3.
2025-07-02 06:41:18.431                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.431                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.431                 # of the computation is cached by cruncher
2025-07-02 06:41:18.431                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.432                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.432                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.432                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.432         if best_ratio < cutoff:
2025-07-02 06:41:18.432             # no non-identical "pretty close" pair
2025-07-02 06:41:18.432             if eqi is None:
2025-07-02 06:41:18.432                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.432                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.432                 return
2025-07-02 06:41:18.432             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.432             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.432         else:
2025-07-02 06:41:18.432             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.432             eqi = None
2025-07-02 06:41:18.432
2025-07-02 06:41:18.432         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.432         # identical
2025-07-02 06:41:18.432
2025-07-02 06:41:18.432         # pump out diffs from before the synch point
2025-07-02 06:41:18.432         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.433
2025-07-02 06:41:18.433         # do intraline marking on the synch pair
2025-07-02 06:41:18.433         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.433         if eqi is None:
2025-07-02 06:41:18.433             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.433             atags = btags = ""
2025-07-02 06:41:18.433             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.433             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.433                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.433                 if tag == 'replace':
2025-07-02 06:41:18.433                     atags += '^' * la
2025-07-02 06:41:18.433                     btags += '^' * lb
2025-07-02 06:41:18.433                 elif tag == 'delete':
2025-07-02 06:41:18.433                     atags += '-' * la
2025-07-02 06:41:18.433                 elif tag == 'insert':
2025-07-02 06:41:18.433                     btags += '+' * lb
2025-07-02 06:41:18.433                 elif tag == 'equal':
2025-07-02 06:41:18.433                     atags += ' ' * la
2025-07-02 06:41:18.433                     btags += ' ' * lb
2025-07-02 06:41:18.433                 else:
2025-07-02 06:41:18.434                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.434             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.434         else:
2025-07-02 06:41:18.434             # the synch pair is identical
2025-07-02 06:41:18.434             yield '  ' + aelt
2025-07-02 06:41:18.434
2025-07-02 06:41:18.434         # pump out diffs from after the synch point
2025-07-02 06:41:18.434 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.434
2025-07-02 06:41:18.434 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.434 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.434
2025-07-02 06:41:18.434 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.434 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.434 alo = 400, ahi = 1101
2025-07-02 06:41:18.434 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.434 blo = 400, bhi = 1101
2025-07-02 06:41:18.434
2025-07-02 06:41:18.434     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.435         g = []
2025-07-02 06:41:18.435         if alo < ahi:
2025-07-02 06:41:18.435             if blo < bhi:
2025-07-02 06:41:18.435                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.435             else:
2025-07-02 06:41:18.435                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.435         elif blo < bhi:
2025-07-02 06:41:18.435             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.435
2025-07-02 06:41:18.435 >       yield from g
2025-07-02 06:41:18.435
2025-07-02 06:41:18.435 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.435 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.435
2025-07-02 06:41:18.435 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.435 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.435 alo = 400, ahi = 1101
2025-07-02 06:41:18.435 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.436 blo = 400, bhi = 1101
2025-07-02 06:41:18.436
2025-07-02 06:41:18.436     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.436         r"""
2025-07-02 06:41:18.436         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.436         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.436         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.436         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.436
2025-07-02 06:41:18.436         Example:
2025-07-02 06:41:18.436
2025-07-02 06:41:18.436         >>> d = Differ()
2025-07-02 06:41:18.436         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.436         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.436         >>> print(''.join(results), end="")
2025-07-02 06:41:18.436         - abcDefghiJkl
2025-07-02 06:41:18.436         + abcdefGhijkl
2025-07-02 06:41:18.436         """
2025-07-02 06:41:18.437
2025-07-02 06:41:18.437         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.437         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.437         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.437         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.437         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.437
2025-07-02 06:41:18.437         # search for the pair that matches best without being identical
2025-07-02 06:41:18.437         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.437         # on junk -- unless we have to)
2025-07-02 06:41:18.437         for j in range(blo, bhi):
2025-07-02 06:41:18.437             bj = b[j]
2025-07-02 06:41:18.437             cruncher.set_seq2(bj)
2025-07-02 06:41:18.437             for i in range(alo, ahi):
2025-07-02 06:41:18.437                 ai = a[i]
2025-07-02 06:41:18.437                 if ai == bj:
2025-07-02 06:41:18.437                     if eqi is None:
2025-07-02 06:41:18.437                         eqi, eqj = i, j
2025-07-02 06:41:18.438                     continue
2025-07-02 06:41:18.438                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.438                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.438                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.438                 # compares by a factor of 3.
2025-07-02 06:41:18.438                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.438                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.438                 # of the computation is cached by cruncher
2025-07-02 06:41:18.438                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.438                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.438                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.438                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.438         if best_ratio < cutoff:
2025-07-02 06:41:18.438             # no non-identical "pretty close" pair
2025-07-02 06:41:18.438             if eqi is None:
2025-07-02 06:41:18.438                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.438                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.438                 return
2025-07-02 06:41:18.438             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.439             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.439         else:
2025-07-02 06:41:18.439             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.439             eqi = None
2025-07-02 06:41:18.439
2025-07-02 06:41:18.439         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.439         # identical
2025-07-02 06:41:18.439
2025-07-02 06:41:18.439         # pump out diffs from before the synch point
2025-07-02 06:41:18.439         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.439
2025-07-02 06:41:18.439         # do intraline marking on the synch pair
2025-07-02 06:41:18.439         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.439         if eqi is None:
2025-07-02 06:41:18.439             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.439             atags = btags = ""
2025-07-02 06:41:18.439             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.439             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.439                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.440                 if tag == 'replace':
2025-07-02 06:41:18.440                     atags += '^' * la
2025-07-02 06:41:18.440                     btags += '^' * lb
2025-07-02 06:41:18.440                 elif tag == 'delete':
2025-07-02 06:41:18.440                     atags += '-' * la
2025-07-02 06:41:18.440                 elif tag == 'insert':
2025-07-02 06:41:18.440                     btags += '+' * lb
2025-07-02 06:41:18.440                 elif tag == 'equal':
2025-07-02 06:41:18.440                     atags += ' ' * la
2025-07-02 06:41:18.440                     btags += ' ' * lb
2025-07-02 06:41:18.440                 else:
2025-07-02 06:41:18.440                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.440             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.440         else:
2025-07-02 06:41:18.440             # the synch pair is identical
2025-07-02 06:41:18.440             yield '  ' + aelt
2025-07-02 06:41:18.440
2025-07-02 06:41:18.440         # pump out diffs from after the synch point
2025-07-02 06:41:18.440 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.440
2025-07-02 06:41:18.440 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.441 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.441
2025-07-02 06:41:18.441 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.441 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.441 alo = 401, ahi = 1101
2025-07-02 06:41:18.441 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.441 blo = 401, bhi = 1101
2025-07-02 06:41:18.441
2025-07-02 06:41:18.441     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.441         g = []
2025-07-02 06:41:18.441         if alo < ahi:
2025-07-02 06:41:18.441             if blo < bhi:
2025-07-02 06:41:18.441                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.441             else:
2025-07-02 06:41:18.441                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.441         elif blo < bhi:
2025-07-02 06:41:18.441             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.441
2025-07-02 06:41:18.441 >       yield from g
2025-07-02 06:41:18.441
2025-07-02 06:41:18.442 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.442 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.442
2025-07-02 06:41:18.442 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.442 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.442 alo = 401, ahi = 1101
2025-07-02 06:41:18.442 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.442 blo = 401, bhi = 1101
2025-07-02 06:41:18.442
2025-07-02 06:41:18.442     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.442         r"""
2025-07-02 06:41:18.442         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.442         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.442         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.442         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.442
2025-07-02 06:41:18.442         Example:
2025-07-02 06:41:18.442
2025-07-02 06:41:18.442         >>> d = Differ()
2025-07-02 06:41:18.442         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.443         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.443         >>> print(''.join(results), end="")
2025-07-02 06:41:18.443         - abcDefghiJkl
2025-07-02 06:41:18.443         + abcdefGhijkl
2025-07-02 06:41:18.443         """
2025-07-02 06:41:18.443
2025-07-02 06:41:18.443         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.443         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.443         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.443         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.443         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.443
2025-07-02 06:41:18.443         # search for the pair that matches best without being identical
2025-07-02 06:41:18.443         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.443         # on junk -- unless we have to)
2025-07-02 06:41:18.443         for j in range(blo, bhi):
2025-07-02 06:41:18.443             bj = b[j]
2025-07-02 06:41:18.443             cruncher.set_seq2(bj)
2025-07-02 06:41:18.443             for i in range(alo, ahi):
2025-07-02 06:41:18.443                 ai = a[i]
2025-07-02 06:41:18.443                 if ai == bj:
2025-07-02 06:41:18.443                     if eqi is None:
2025-07-02 06:41:18.444                         eqi, eqj = i, j
2025-07-02 06:41:18.444                     continue
2025-07-02 06:41:18.444                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.444                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.444                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.444                 # compares by a factor of 3.
2025-07-02 06:41:18.444                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.444                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.444                 # of the computation is cached by cruncher
2025-07-02 06:41:18.444                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.444                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.444                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.444                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.444         if best_ratio < cutoff:
2025-07-02 06:41:18.444             # no non-identical "pretty close" pair
2025-07-02 06:41:18.444             if eqi is None:
2025-07-02 06:41:18.444                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.444                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.444                 return
2025-07-02 06:41:18.445             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.445             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.445         else:
2025-07-02 06:41:18.445             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.445             eqi = None
2025-07-02 06:41:18.445
2025-07-02 06:41:18.445         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.445         # identical
2025-07-02 06:41:18.445
2025-07-02 06:41:18.445         # pump out diffs from before the synch point
2025-07-02 06:41:18.445         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.445
2025-07-02 06:41:18.445         # do intraline marking on the synch pair
2025-07-02 06:41:18.445         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.445         if eqi is None:
2025-07-02 06:41:18.445             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.445             atags = btags = ""
2025-07-02 06:41:18.445             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.445             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.445                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.446                 if tag == 'replace':
2025-07-02 06:41:18.446                     atags += '^' * la
2025-07-02 06:41:18.446                     btags += '^' * lb
2025-07-02 06:41:18.446                 elif tag == 'delete':
2025-07-02 06:41:18.446                     atags += '-' * la
2025-07-02 06:41:18.446                 elif tag == 'insert':
2025-07-02 06:41:18.446                     btags += '+' * lb
2025-07-02 06:41:18.446                 elif tag == 'equal':
2025-07-02 06:41:18.446                     atags += ' ' * la
2025-07-02 06:41:18.446                     btags += ' ' * lb
2025-07-02 06:41:18.446                 else:
2025-07-02 06:41:18.446                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.446             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.446         else:
2025-07-02 06:41:18.446             # the synch pair is identical
2025-07-02 06:41:18.446             yield '  ' + aelt
2025-07-02 06:41:18.446
2025-07-02 06:41:18.446         # pump out diffs from after the synch point
2025-07-02 06:41:18.446 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.447
2025-07-02 06:41:18.447 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.447 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.447
2025-07-02 06:41:18.447 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.447 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.447 alo = 402, ahi = 1101
2025-07-02 06:41:18.447 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.447 blo = 402, bhi = 1101
2025-07-02 06:41:18.447
2025-07-02 06:41:18.447     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.447         g = []
2025-07-02 06:41:18.447         if alo < ahi:
2025-07-02 06:41:18.447             if blo < bhi:
2025-07-02 06:41:18.447                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.447             else:
2025-07-02 06:41:18.447                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.447         elif blo < bhi:
2025-07-02 06:41:18.447             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448 >       yield from g
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.448 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.448 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.448 alo = 402, ahi = 1101
2025-07-02 06:41:18.448 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.448 blo = 402, bhi = 1101
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.448         r"""
2025-07-02 06:41:18.448         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.448         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.448         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.448         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.448
2025-07-02 06:41:18.448         Example:
2025-07-02 06:41:18.449
2025-07-02 06:41:18.449         >>> d = Differ()
2025-07-02 06:41:18.449         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.449         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.449         >>> print(''.join(results), end="")
2025-07-02 06:41:18.449         - abcDefghiJkl
2025-07-02 06:41:18.449         + abcdefGhijkl
2025-07-02 06:41:18.449         """
2025-07-02 06:41:18.449
2025-07-02 06:41:18.449         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.449         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.449         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.449         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.449         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.449
2025-07-02 06:41:18.449         # search for the pair that matches best without being identical
2025-07-02 06:41:18.449         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.450         # on junk -- unless we have to)
2025-07-02 06:41:18.450         for j in range(blo, bhi):
2025-07-02 06:41:18.450             bj = b[j]
2025-07-02 06:41:18.450             cruncher.set_seq2(bj)
2025-07-02 06:41:18.450             for i in range(alo, ahi):
2025-07-02 06:41:18.450                 ai = a[i]
2025-07-02 06:41:18.450                 if ai == bj:
2025-07-02 06:41:18.450                     if eqi is None:
2025-07-02 06:41:18.450                         eqi, eqj = i, j
2025-07-02 06:41:18.450                     continue
2025-07-02 06:41:18.450                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.450                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.450                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.450                 # compares by a factor of 3.
2025-07-02 06:41:18.450                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.450                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.450                 # of the computation is cached by cruncher
2025-07-02 06:41:18.450                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.450                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.450                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.451                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.451         if best_ratio < cutoff:
2025-07-02 06:41:18.451             # no non-identical "pretty close" pair
2025-07-02 06:41:18.451             if eqi is None:
2025-07-02 06:41:18.451                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.451                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.451                 return
2025-07-02 06:41:18.451             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.451             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.451         else:
2025-07-02 06:41:18.451             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.451             eqi = None
2025-07-02 06:41:18.451
2025-07-02 06:41:18.451         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.451         # identical
2025-07-02 06:41:18.451
2025-07-02 06:41:18.451         # pump out diffs from before the synch point
2025-07-02 06:41:18.451         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.452
2025-07-02 06:41:18.452         # do intraline marking on the synch pair
2025-07-02 06:41:18.452         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.452         if eqi is None:
2025-07-02 06:41:18.452             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.452             atags = btags = ""
2025-07-02 06:41:18.452             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.452             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.452                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.452                 if tag == 'replace':
2025-07-02 06:41:18.452                     atags += '^' * la
2025-07-02 06:41:18.452                     btags += '^' * lb
2025-07-02 06:41:18.452                 elif tag == 'delete':
2025-07-02 06:41:18.452                     atags += '-' * la
2025-07-02 06:41:18.452                 elif tag == 'insert':
2025-07-02 06:41:18.452                     btags += '+' * lb
2025-07-02 06:41:18.452                 elif tag == 'equal':
2025-07-02 06:41:18.452                     atags += ' ' * la
2025-07-02 06:41:18.452                     btags += ' ' * lb
2025-07-02 06:41:18.453                 else:
2025-07-02 06:41:18.453                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.453             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.453         else:
2025-07-02 06:41:18.453             # the synch pair is identical
2025-07-02 06:41:18.453             yield '  ' + aelt
2025-07-02 06:41:18.453
2025-07-02 06:41:18.453         # pump out diffs from after the synch point
2025-07-02 06:41:18.453 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.453
2025-07-02 06:41:18.453 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.453 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.453
2025-07-02 06:41:18.453 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.453 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.453 alo = 403, ahi = 1101
2025-07-02 06:41:18.453 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.453 blo = 403, bhi = 1101
2025-07-02 06:41:18.453
2025-07-02 06:41:18.454     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.454         g = []
2025-07-02 06:41:18.454         if alo < ahi:
2025-07-02 06:41:18.454             if blo < bhi:
2025-07-02 06:41:18.454                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.454             else:
2025-07-02 06:41:18.454                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.454         elif blo < bhi:
2025-07-02 06:41:18.454             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.454
2025-07-02 06:41:18.454 >       yield from g
2025-07-02 06:41:18.454
2025-07-02 06:41:18.454 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.454 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.454
2025-07-02 06:41:18.454 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.454 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.454 alo = 403, ahi = 1101
2025-07-02 06:41:18.454 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.455 blo = 403, bhi = 1101
2025-07-02 06:41:18.455
2025-07-02 06:41:18.455     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.455         r"""
2025-07-02 06:41:18.455         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.455         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.455         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.455         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.455
2025-07-02 06:41:18.455         Example:
2025-07-02 06:41:18.455
2025-07-02 06:41:18.455         >>> d = Differ()
2025-07-02 06:41:18.455         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.455         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.455         >>> print(''.join(results), end="")
2025-07-02 06:41:18.455         - abcDefghiJkl
2025-07-02 06:41:18.455         + abcdefGhijkl
2025-07-02 06:41:18.456         """
2025-07-02 06:41:18.456
2025-07-02 06:41:18.456         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.456         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.456         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.456         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.456         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.456
2025-07-02 06:41:18.456         # search for the pair that matches best without being identical
2025-07-02 06:41:18.456         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.456         # on junk -- unless we have to)
2025-07-02 06:41:18.456         for j in range(blo, bhi):
2025-07-02 06:41:18.456             bj = b[j]
2025-07-02 06:41:18.456             cruncher.set_seq2(bj)
2025-07-02 06:41:18.456             for i in range(alo, ahi):
2025-07-02 06:41:18.456                 ai = a[i]
2025-07-02 06:41:18.456                 if ai == bj:
2025-07-02 06:41:18.456                     if eqi is None:
2025-07-02 06:41:18.457                         eqi, eqj = i, j
2025-07-02 06:41:18.457                     continue
2025-07-02 06:41:18.457                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.457                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.457                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.457                 # compares by a factor of 3.
2025-07-02 06:41:18.457                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.457                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.457                 # of the computation is cached by cruncher
2025-07-02 06:41:18.457                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.457                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.457                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.457                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.457         if best_ratio < cutoff:
2025-07-02 06:41:18.457             # no non-identical "pretty close" pair
2025-07-02 06:41:18.457             if eqi is None:
2025-07-02 06:41:18.457                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.457                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.457                 return
2025-07-02 06:41:18.458             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.458             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.458         else:
2025-07-02 06:41:18.458             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.458             eqi = None
2025-07-02 06:41:18.458
2025-07-02 06:41:18.458         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.458         # identical
2025-07-02 06:41:18.458
2025-07-02 06:41:18.458         # pump out diffs from before the synch point
2025-07-02 06:41:18.458         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.458
2025-07-02 06:41:18.458         # do intraline marking on the synch pair
2025-07-02 06:41:18.458         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.458         if eqi is None:
2025-07-02 06:41:18.458             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.458             atags = btags = ""
2025-07-02 06:41:18.458             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.458             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.459                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.459                 if tag == 'replace':
2025-07-02 06:41:18.459                     atags += '^' * la
2025-07-02 06:41:18.459                     btags += '^' * lb
2025-07-02 06:41:18.459                 elif tag == 'delete':
2025-07-02 06:41:18.459                     atags += '-' * la
2025-07-02 06:41:18.459                 elif tag == 'insert':
2025-07-02 06:41:18.459                     btags += '+' * lb
2025-07-02 06:41:18.459                 elif tag == 'equal':
2025-07-02 06:41:18.459                     atags += ' ' * la
2025-07-02 06:41:18.459                     btags += ' ' * lb
2025-07-02 06:41:18.459                 else:
2025-07-02 06:41:18.459                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.459             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.459         else:
2025-07-02 06:41:18.459             # the synch pair is identical
2025-07-02 06:41:18.459             yield '  ' + aelt
2025-07-02 06:41:18.459
2025-07-02 06:41:18.459         # pump out diffs from after the synch point
2025-07-02 06:41:18.459 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.460
2025-07-02 06:41:18.460 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.460 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.460
2025-07-02 06:41:18.460 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.460 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.460 alo = 404, ahi = 1101
2025-07-02 06:41:18.460 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.460 blo = 404, bhi = 1101
2025-07-02 06:41:18.460
2025-07-02 06:41:18.460     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.460         g = []
2025-07-02 06:41:18.460         if alo < ahi:
2025-07-02 06:41:18.460             if blo < bhi:
2025-07-02 06:41:18.460                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.460             else:
2025-07-02 06:41:18.460                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.460         elif blo < bhi:
2025-07-02 06:41:18.461             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.461
2025-07-02 06:41:18.461 >       yield from g
2025-07-02 06:41:18.461
2025-07-02 06:41:18.461 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.461 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.461
2025-07-02 06:41:18.461 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.461 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.461 alo = 404, ahi = 1101
2025-07-02 06:41:18.461 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.461 blo = 404, bhi = 1101
2025-07-02 06:41:18.461
2025-07-02 06:41:18.461     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.461         r"""
2025-07-02 06:41:18.461         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.461         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.461         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.461         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.462
2025-07-02 06:41:18.462         Example:
2025-07-02 06:41:18.462
2025-07-02 06:41:18.462         >>> d = Differ()
2025-07-02 06:41:18.462         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.462         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.462         >>> print(''.join(results), end="")
2025-07-02 06:41:18.462         - abcDefghiJkl
2025-07-02 06:41:18.462         + abcdefGhijkl
2025-07-02 06:41:18.462         """
2025-07-02 06:41:18.462
2025-07-02 06:41:18.462         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.462         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.462         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.462         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.462         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.462
2025-07-02 06:41:18.463         # search for the pair that matches best without being identical
2025-07-02 06:41:18.463         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.463         # on junk -- unless we have to)
2025-07-02 06:41:18.463         for j in range(blo, bhi):
2025-07-02 06:41:18.463             bj = b[j]
2025-07-02 06:41:18.463             cruncher.set_seq2(bj)
2025-07-02 06:41:18.463             for i in range(alo, ahi):
2025-07-02 06:41:18.463                 ai = a[i]
2025-07-02 06:41:18.463                 if ai == bj:
2025-07-02 06:41:18.463                     if eqi is None:
2025-07-02 06:41:18.463                         eqi, eqj = i, j
2025-07-02 06:41:18.463                     continue
2025-07-02 06:41:18.463                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.463                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.463                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.463                 # compares by a factor of 3.
2025-07-02 06:41:18.463                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.463                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.463                 # of the computation is cached by cruncher
2025-07-02 06:41:18.464                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.464                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.464                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.464                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.464         if best_ratio < cutoff:
2025-07-02 06:41:18.464             # no non-identical "pretty close" pair
2025-07-02 06:41:18.464             if eqi is None:
2025-07-02 06:41:18.464                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.464                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.464                 return
2025-07-02 06:41:18.464             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.464             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.464         else:
2025-07-02 06:41:18.464             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.464             eqi = None
2025-07-02 06:41:18.464
2025-07-02 06:41:18.464         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.464         # identical
2025-07-02 06:41:18.464
2025-07-02 06:41:18.465         # pump out diffs from before the synch point
2025-07-02 06:41:18.465         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.465
2025-07-02 06:41:18.465         # do intraline marking on the synch pair
2025-07-02 06:41:18.465         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.465         if eqi is None:
2025-07-02 06:41:18.465             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.465             atags = btags = ""
2025-07-02 06:41:18.465             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.465             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.465                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.465                 if tag == 'replace':
2025-07-02 06:41:18.465                     atags += '^' * la
2025-07-02 06:41:18.465                     btags += '^' * lb
2025-07-02 06:41:18.465                 elif tag == 'delete':
2025-07-02 06:41:18.465                     atags += '-' * la
2025-07-02 06:41:18.465                 elif tag == 'insert':
2025-07-02 06:41:18.465                     btags += '+' * lb
2025-07-02 06:41:18.465                 elif tag == 'equal':
2025-07-02 06:41:18.466                     atags += ' ' * la
2025-07-02 06:41:18.466                     btags += ' ' * lb
2025-07-02 06:41:18.466                 else:
2025-07-02 06:41:18.466                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.466             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.466         else:
2025-07-02 06:41:18.466             # the synch pair is identical
2025-07-02 06:41:18.466             yield '  ' + aelt
2025-07-02 06:41:18.466
2025-07-02 06:41:18.466         # pump out diffs from after the synch point
2025-07-02 06:41:18.466 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.466
2025-07-02 06:41:18.466 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.466 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.466
2025-07-02 06:41:18.466 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.466 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.466 alo = 405, ahi = 1101
2025-07-02 06:41:18.466 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.467 blo = 405, bhi = 1101
2025-07-02 06:41:18.467
2025-07-02 06:41:18.467     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.467         g = []
2025-07-02 06:41:18.467         if alo < ahi:
2025-07-02 06:41:18.467             if blo < bhi:
2025-07-02 06:41:18.467                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.467             else:
2025-07-02 06:41:18.467                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.467         elif blo < bhi:
2025-07-02 06:41:18.467             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.467
2025-07-02 06:41:18.467 >       yield from g
2025-07-02 06:41:18.467
2025-07-02 06:41:18.467 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.467 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.467
2025-07-02 06:41:18.467 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.468 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.468 alo = 405, ahi = 1101
2025-07-02 06:41:18.468 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.468 blo = 405, bhi = 1101
2025-07-02 06:41:18.468
2025-07-02 06:41:18.468     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.468         r"""
2025-07-02 06:41:18.468         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.468         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.468         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.468         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.468
2025-07-02 06:41:18.468         Example:
2025-07-02 06:41:18.468
2025-07-02 06:41:18.468         >>> d = Differ()
2025-07-02 06:41:18.468         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.468         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.468         >>> print(''.join(results), end="")
2025-07-02 06:41:18.468         - abcDefghiJkl
2025-07-02 06:41:18.469         + abcdefGhijkl
2025-07-02 06:41:18.469         """
2025-07-02 06:41:18.469
2025-07-02 06:41:18.469         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.469         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.469         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.469         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.469         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.469
2025-07-02 06:41:18.469         # search for the pair that matches best without being identical
2025-07-02 06:41:18.469         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.469         # on junk -- unless we have to)
2025-07-02 06:41:18.469         for j in range(blo, bhi):
2025-07-02 06:41:18.469             bj = b[j]
2025-07-02 06:41:18.469             cruncher.set_seq2(bj)
2025-07-02 06:41:18.469             for i in range(alo, ahi):
2025-07-02 06:41:18.469                 ai = a[i]
2025-07-02 06:41:18.470                 if ai == bj:
2025-07-02 06:41:18.470                     if eqi is None:
2025-07-02 06:41:18.470                         eqi, eqj = i, j
2025-07-02 06:41:18.470                     continue
2025-07-02 06:41:18.470                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.470                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.470                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.470                 # compares by a factor of 3.
2025-07-02 06:41:18.470                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.470                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.470                 # of the computation is cached by cruncher
2025-07-02 06:41:18.470                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.470                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.470                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.470                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.470         if best_ratio < cutoff:
2025-07-02 06:41:18.470             # no non-identical "pretty close" pair
2025-07-02 06:41:18.470             if eqi is None:
2025-07-02 06:41:18.471                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.471                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.471                 return
2025-07-02 06:41:18.471             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.471             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.471         else:
2025-07-02 06:41:18.471             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.471             eqi = None
2025-07-02 06:41:18.471
2025-07-02 06:41:18.471         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.471         # identical
2025-07-02 06:41:18.471
2025-07-02 06:41:18.471         # pump out diffs from before the synch point
2025-07-02 06:41:18.471         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.471
2025-07-02 06:41:18.471         # do intraline marking on the synch pair
2025-07-02 06:41:18.471         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.471         if eqi is None:
2025-07-02 06:41:18.471             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.472             atags = btags = ""
2025-07-02 06:41:18.472             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.472             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.472                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.472                 if tag == 'replace':
2025-07-02 06:41:18.472                     atags += '^' * la
2025-07-02 06:41:18.472                     btags += '^' * lb
2025-07-02 06:41:18.472                 elif tag == 'delete':
2025-07-02 06:41:18.472                     atags += '-' * la
2025-07-02 06:41:18.472                 elif tag == 'insert':
2025-07-02 06:41:18.472                     btags += '+' * lb
2025-07-02 06:41:18.472                 elif tag == 'equal':
2025-07-02 06:41:18.472                     atags += ' ' * la
2025-07-02 06:41:18.472                     btags += ' ' * lb
2025-07-02 06:41:18.472                 else:
2025-07-02 06:41:18.472                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.472             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.472         else:
2025-07-02 06:41:18.472             # the synch pair is identical
2025-07-02 06:41:18.473             yield '  ' + aelt
2025-07-02 06:41:18.473
2025-07-02 06:41:18.473         # pump out diffs from after the synch point
2025-07-02 06:41:18.473 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.473
2025-07-02 06:41:18.473 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.473 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.473
2025-07-02 06:41:18.473 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.473 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.473 alo = 406, ahi = 1101
2025-07-02 06:41:18.473 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.473 blo = 406, bhi = 1101
2025-07-02 06:41:18.473
2025-07-02 06:41:18.473     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.473         g = []
2025-07-02 06:41:18.473         if alo < ahi:
2025-07-02 06:41:18.473             if blo < bhi:
2025-07-02 06:41:18.473                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.474             else:
2025-07-02 06:41:18.474                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.474         elif blo < bhi:
2025-07-02 06:41:18.474             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.474
2025-07-02 06:41:18.474 >       yield from g
2025-07-02 06:41:18.474
2025-07-02 06:41:18.474 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.474 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.474
2025-07-02 06:41:18.474 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.474 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.474 alo = 406, ahi = 1101
2025-07-02 06:41:18.474 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.474 blo = 406, bhi = 1101
2025-07-02 06:41:18.474
2025-07-02 06:41:18.474     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.474         r"""
2025-07-02 06:41:18.474         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.475         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.475         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.475         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.475
2025-07-02 06:41:18.475         Example:
2025-07-02 06:41:18.475
2025-07-02 06:41:18.475         >>> d = Differ()
2025-07-02 06:41:18.475         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.475         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.475         >>> print(''.join(results), end="")
2025-07-02 06:41:18.475         - abcDefghiJkl
2025-07-02 06:41:18.475         + abcdefGhijkl
2025-07-02 06:41:18.475         """
2025-07-02 06:41:18.475
2025-07-02 06:41:18.475         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.475         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.475         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.476         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.476         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.476
2025-07-02 06:41:18.476         # search for the pair that matches best without being identical
2025-07-02 06:41:18.476         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.476         # on junk -- unless we have to)
2025-07-02 06:41:18.476         for j in range(blo, bhi):
2025-07-02 06:41:18.476             bj = b[j]
2025-07-02 06:41:18.476             cruncher.set_seq2(bj)
2025-07-02 06:41:18.476             for i in range(alo, ahi):
2025-07-02 06:41:18.476                 ai = a[i]
2025-07-02 06:41:18.476                 if ai == bj:
2025-07-02 06:41:18.476                     if eqi is None:
2025-07-02 06:41:18.476                         eqi, eqj = i, j
2025-07-02 06:41:18.476                     continue
2025-07-02 06:41:18.476                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.476                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.476                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.476                 # compares by a factor of 3.
2025-07-02 06:41:18.477                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.477                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.477                 # of the computation is cached by cruncher
2025-07-02 06:41:18.477                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.477                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.477                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.477                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.477         if best_ratio < cutoff:
2025-07-02 06:41:18.477             # no non-identical "pretty close" pair
2025-07-02 06:41:18.477             if eqi is None:
2025-07-02 06:41:18.477                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.477                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.477                 return
2025-07-02 06:41:18.477             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.477             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.477         else:
2025-07-02 06:41:18.477             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.477             eqi = None
2025-07-02 06:41:18.477
2025-07-02 06:41:18.478         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.478         # identical
2025-07-02 06:41:18.478
2025-07-02 06:41:18.478         # pump out diffs from before the synch point
2025-07-02 06:41:18.478         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.478
2025-07-02 06:41:18.478         # do intraline marking on the synch pair
2025-07-02 06:41:18.478         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.478         if eqi is None:
2025-07-02 06:41:18.478             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.478             atags = btags = ""
2025-07-02 06:41:18.478             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.478             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.478                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.478                 if tag == 'replace':
2025-07-02 06:41:18.478                     atags += '^' * la
2025-07-02 06:41:18.478                     btags += '^' * lb
2025-07-02 06:41:18.478                 elif tag == 'delete':
2025-07-02 06:41:18.478                     atags += '-' * la
2025-07-02 06:41:18.479                 elif tag == 'insert':
2025-07-02 06:41:18.479                     btags += '+' * lb
2025-07-02 06:41:18.479                 elif tag == 'equal':
2025-07-02 06:41:18.479                     atags += ' ' * la
2025-07-02 06:41:18.479                     btags += ' ' * lb
2025-07-02 06:41:18.479                 else:
2025-07-02 06:41:18.479                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.479             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.479         else:
2025-07-02 06:41:18.479             # the synch pair is identical
2025-07-02 06:41:18.479             yield '  ' + aelt
2025-07-02 06:41:18.479
2025-07-02 06:41:18.479         # pump out diffs from after the synch point
2025-07-02 06:41:18.479 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.479
2025-07-02 06:41:18.479 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.479 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.479
2025-07-02 06:41:18.479 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.480 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.480 alo = 407, ahi = 1101
2025-07-02 06:41:18.480 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.480 blo = 407, bhi = 1101
2025-07-02 06:41:18.480
2025-07-02 06:41:18.480     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.480         g = []
2025-07-02 06:41:18.480         if alo < ahi:
2025-07-02 06:41:18.480             if blo < bhi:
2025-07-02 06:41:18.480                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.480             else:
2025-07-02 06:41:18.480                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.480         elif blo < bhi:
2025-07-02 06:41:18.480             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.480
2025-07-02 06:41:18.480 >       yield from g
2025-07-02 06:41:18.480
2025-07-02 06:41:18.480 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.481 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.481
2025-07-02 06:41:18.481 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.481 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.481 alo = 407, ahi = 1101
2025-07-02 06:41:18.481 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.481 blo = 407, bhi = 1101
2025-07-02 06:41:18.481
2025-07-02 06:41:18.481     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.481         r"""
2025-07-02 06:41:18.481         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.481         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.481         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.481         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.481
2025-07-02 06:41:18.481         Example:
2025-07-02 06:41:18.481
2025-07-02 06:41:18.481         >>> d = Differ()
2025-07-02 06:41:18.481         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.482         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.482         >>> print(''.join(results), end="")
2025-07-02 06:41:18.482         - abcDefghiJkl
2025-07-02 06:41:18.482         + abcdefGhijkl
2025-07-02 06:41:18.482         """
2025-07-02 06:41:18.482
2025-07-02 06:41:18.482         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.482         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.482         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.482         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.482         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.482
2025-07-02 06:41:18.482         # search for the pair that matches best without being identical
2025-07-02 06:41:18.482         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.482         # on junk -- unless we have to)
2025-07-02 06:41:18.482         for j in range(blo, bhi):
2025-07-02 06:41:18.482             bj = b[j]
2025-07-02 06:41:18.483             cruncher.set_seq2(bj)
2025-07-02 06:41:18.483             for i in range(alo, ahi):
2025-07-02 06:41:18.483                 ai = a[i]
2025-07-02 06:41:18.483                 if ai == bj:
2025-07-02 06:41:18.483                     if eqi is None:
2025-07-02 06:41:18.483                         eqi, eqj = i, j
2025-07-02 06:41:18.483                     continue
2025-07-02 06:41:18.483                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.483                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.483                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.483                 # compares by a factor of 3.
2025-07-02 06:41:18.483                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.483                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.483                 # of the computation is cached by cruncher
2025-07-02 06:41:18.483                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.483                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.483                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.483                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.483         if best_ratio < cutoff:
2025-07-02 06:41:18.484             # no non-identical "pretty close" pair
2025-07-02 06:41:18.484             if eqi is None:
2025-07-02 06:41:18.484                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.484                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.484                 return
2025-07-02 06:41:18.484             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.484             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.484         else:
2025-07-02 06:41:18.484             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.484             eqi = None
2025-07-02 06:41:18.484
2025-07-02 06:41:18.484         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.484         # identical
2025-07-02 06:41:18.484
2025-07-02 06:41:18.484         # pump out diffs from before the synch point
2025-07-02 06:41:18.484         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.484
2025-07-02 06:41:18.484         # do intraline marking on the synch pair
2025-07-02 06:41:18.484         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.485         if eqi is None:
2025-07-02 06:41:18.485             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.485             atags = btags = ""
2025-07-02 06:41:18.485             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.485             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.485                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.485                 if tag == 'replace':
2025-07-02 06:41:18.485                     atags += '^' * la
2025-07-02 06:41:18.485                     btags += '^' * lb
2025-07-02 06:41:18.485                 elif tag == 'delete':
2025-07-02 06:41:18.485                     atags += '-' * la
2025-07-02 06:41:18.485                 elif tag == 'insert':
2025-07-02 06:41:18.485                     btags += '+' * lb
2025-07-02 06:41:18.485                 elif tag == 'equal':
2025-07-02 06:41:18.485                     atags += ' ' * la
2025-07-02 06:41:18.485                     btags += ' ' * lb
2025-07-02 06:41:18.485                 else:
2025-07-02 06:41:18.485                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.485             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.486         else:
2025-07-02 06:41:18.486             # the synch pair is identical
2025-07-02 06:41:18.486             yield '  ' + aelt
2025-07-02 06:41:18.486
2025-07-02 06:41:18.486         # pump out diffs from after the synch point
2025-07-02 06:41:18.486 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.486
2025-07-02 06:41:18.486 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.486 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.486
2025-07-02 06:41:18.486 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.486 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.486 alo = 408, ahi = 1101
2025-07-02 06:41:18.486 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.486 blo = 408, bhi = 1101
2025-07-02 06:41:18.486
2025-07-02 06:41:18.486     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.486         g = []
2025-07-02 06:41:18.486         if alo < ahi:
2025-07-02 06:41:18.487             if blo < bhi:
2025-07-02 06:41:18.487                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.487             else:
2025-07-02 06:41:18.487                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.487         elif blo < bhi:
2025-07-02 06:41:18.487             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.487
2025-07-02 06:41:18.487 >       yield from g
2025-07-02 06:41:18.487
2025-07-02 06:41:18.487 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.487 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.487
2025-07-02 06:41:18.487 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.487 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.487 alo = 408, ahi = 1101
2025-07-02 06:41:18.487 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.487 blo = 408, bhi = 1101
2025-07-02 06:41:18.487
2025-07-02 06:41:18.487     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.488         r"""
2025-07-02 06:41:18.488         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.488         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.488         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.488         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.488
2025-07-02 06:41:18.488         Example:
2025-07-02 06:41:18.488
2025-07-02 06:41:18.488         >>> d = Differ()
2025-07-02 06:41:18.488         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.488         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.488         >>> print(''.join(results), end="")
2025-07-02 06:41:18.488         - abcDefghiJkl
2025-07-02 06:41:18.488         + abcdefGhijkl
2025-07-02 06:41:18.488         """
2025-07-02 06:41:18.488
2025-07-02 06:41:18.489         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.489         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.489         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.489         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.489         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.489
2025-07-02 06:41:18.489         # search for the pair that matches best without being identical
2025-07-02 06:41:18.489         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.489         # on junk -- unless we have to)
2025-07-02 06:41:18.489         for j in range(blo, bhi):
2025-07-02 06:41:18.489             bj = b[j]
2025-07-02 06:41:18.489             cruncher.set_seq2(bj)
2025-07-02 06:41:18.489             for i in range(alo, ahi):
2025-07-02 06:41:18.489                 ai = a[i]
2025-07-02 06:41:18.489                 if ai == bj:
2025-07-02 06:41:18.489                     if eqi is None:
2025-07-02 06:41:18.489                         eqi, eqj = i, j
2025-07-02 06:41:18.489                     continue
2025-07-02 06:41:18.489                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.490                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.490                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.490                 # compares by a factor of 3.
2025-07-02 06:41:18.490                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.490                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.490                 # of the computation is cached by cruncher
2025-07-02 06:41:18.490                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.490                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.490                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.490                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.490         if best_ratio < cutoff:
2025-07-02 06:41:18.490             # no non-identical "pretty close" pair
2025-07-02 06:41:18.490             if eqi is None:
2025-07-02 06:41:18.490                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.490                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.490                 return
2025-07-02 06:41:18.490             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.490             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.490         else:
2025-07-02 06:41:18.491             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.491             eqi = None
2025-07-02 06:41:18.491
2025-07-02 06:41:18.491         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.491         # identical
2025-07-02 06:41:18.491
2025-07-02 06:41:18.491         # pump out diffs from before the synch point
2025-07-02 06:41:18.491         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.491
2025-07-02 06:41:18.491         # do intraline marking on the synch pair
2025-07-02 06:41:18.491         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.491         if eqi is None:
2025-07-02 06:41:18.491             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.491             atags = btags = ""
2025-07-02 06:41:18.491             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.491             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.491                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.491                 if tag == 'replace':
2025-07-02 06:41:18.491                     atags += '^' * la
2025-07-02 06:41:18.492                     btags += '^' * lb
2025-07-02 06:41:18.492                 elif tag == 'delete':
2025-07-02 06:41:18.492                     atags += '-' * la
2025-07-02 06:41:18.492                 elif tag == 'insert':
2025-07-02 06:41:18.492                     btags += '+' * lb
2025-07-02 06:41:18.492                 elif tag == 'equal':
2025-07-02 06:41:18.492                     atags += ' ' * la
2025-07-02 06:41:18.492                     btags += ' ' * lb
2025-07-02 06:41:18.492                 else:
2025-07-02 06:41:18.492                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.492             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.492         else:
2025-07-02 06:41:18.492             # the synch pair is identical
2025-07-02 06:41:18.492             yield '  ' + aelt
2025-07-02 06:41:18.492
2025-07-02 06:41:18.492         # pump out diffs from after the synch point
2025-07-02 06:41:18.492 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.492
2025-07-02 06:41:18.492 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.492 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.493
2025-07-02 06:41:18.493 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.493 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.493 alo = 409, ahi = 1101
2025-07-02 06:41:18.493 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.493 blo = 409, bhi = 1101
2025-07-02 06:41:18.493
2025-07-02 06:41:18.493     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.493         g = []
2025-07-02 06:41:18.493         if alo < ahi:
2025-07-02 06:41:18.493             if blo < bhi:
2025-07-02 06:41:18.493                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.493             else:
2025-07-02 06:41:18.493                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.493         elif blo < bhi:
2025-07-02 06:41:18.493             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.493
2025-07-02 06:41:18.493 >       yield from g
2025-07-02 06:41:18.494
2025-07-02 06:41:18.494 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.494 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.494
2025-07-02 06:41:18.494 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.494 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.494 alo = 409, ahi = 1101
2025-07-02 06:41:18.494 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.494 blo = 409, bhi = 1101
2025-07-02 06:41:18.494
2025-07-02 06:41:18.494     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.494         r"""
2025-07-02 06:41:18.494         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.494         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.494         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.494         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.494
2025-07-02 06:41:18.494         Example:
2025-07-02 06:41:18.494
2025-07-02 06:41:18.495         >>> d = Differ()
2025-07-02 06:41:18.495         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.495         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.495         >>> print(''.join(results), end="")
2025-07-02 06:41:18.495         - abcDefghiJkl
2025-07-02 06:41:18.495         + abcdefGhijkl
2025-07-02 06:41:18.495         """
2025-07-02 06:41:18.495
2025-07-02 06:41:18.495         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.495         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.495         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.495         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.495         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.495
2025-07-02 06:41:18.495         # search for the pair that matches best without being identical
2025-07-02 06:41:18.495         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.496         # on junk -- unless we have to)
2025-07-02 06:41:18.496         for j in range(blo, bhi):
2025-07-02 06:41:18.496             bj = b[j]
2025-07-02 06:41:18.496             cruncher.set_seq2(bj)
2025-07-02 06:41:18.496             for i in range(alo, ahi):
2025-07-02 06:41:18.496                 ai = a[i]
2025-07-02 06:41:18.496                 if ai == bj:
2025-07-02 06:41:18.496                     if eqi is None:
2025-07-02 06:41:18.496                         eqi, eqj = i, j
2025-07-02 06:41:18.496                     continue
2025-07-02 06:41:18.496                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.496                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.496                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.496                 # compares by a factor of 3.
2025-07-02 06:41:18.496                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.496                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.496                 # of the computation is cached by cruncher
2025-07-02 06:41:18.496                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.496                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.496                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.497                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.497         if best_ratio < cutoff:
2025-07-02 06:41:18.497             # no non-identical "pretty close" pair
2025-07-02 06:41:18.497             if eqi is None:
2025-07-02 06:41:18.497                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.497                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.497                 return
2025-07-02 06:41:18.497             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.497             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.497         else:
2025-07-02 06:41:18.497             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.497             eqi = None
2025-07-02 06:41:18.497
2025-07-02 06:41:18.497         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.497         # identical
2025-07-02 06:41:18.497
2025-07-02 06:41:18.497         # pump out diffs from before the synch point
2025-07-02 06:41:18.498         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.498
2025-07-02 06:41:18.498         # do intraline marking on the synch pair
2025-07-02 06:41:18.498         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.498         if eqi is None:
2025-07-02 06:41:18.498             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.498             atags = btags = ""
2025-07-02 06:41:18.498             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.498             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.498                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.498                 if tag == 'replace':
2025-07-02 06:41:18.498                     atags += '^' * la
2025-07-02 06:41:18.498                     btags += '^' * lb
2025-07-02 06:41:18.498                 elif tag == 'delete':
2025-07-02 06:41:18.498                     atags += '-' * la
2025-07-02 06:41:18.498                 elif tag == 'insert':
2025-07-02 06:41:18.498                     btags += '+' * lb
2025-07-02 06:41:18.498                 elif tag == 'equal':
2025-07-02 06:41:18.498                     atags += ' ' * la
2025-07-02 06:41:18.499                     btags += ' ' * lb
2025-07-02 06:41:18.499                 else:
2025-07-02 06:41:18.499                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.499             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.499         else:
2025-07-02 06:41:18.499             # the synch pair is identical
2025-07-02 06:41:18.499             yield '  ' + aelt
2025-07-02 06:41:18.499
2025-07-02 06:41:18.499         # pump out diffs from after the synch point
2025-07-02 06:41:18.499 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.499
2025-07-02 06:41:18.499 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.499 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.499
2025-07-02 06:41:18.499 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.499 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.499 alo = 410, ahi = 1101
2025-07-02 06:41:18.499 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.500 blo = 410, bhi = 1101
2025-07-02 06:41:18.500
2025-07-02 06:41:18.500     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.500         g = []
2025-07-02 06:41:18.500         if alo < ahi:
2025-07-02 06:41:18.500             if blo < bhi:
2025-07-02 06:41:18.500                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.500             else:
2025-07-02 06:41:18.500                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.500         elif blo < bhi:
2025-07-02 06:41:18.500             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.500
2025-07-02 06:41:18.500 >       yield from g
2025-07-02 06:41:18.500
2025-07-02 06:41:18.500 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.500 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.500
2025-07-02 06:41:18.500 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.500 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.501 alo = 410, ahi = 1101
2025-07-02 06:41:18.501 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.501 blo = 410, bhi = 1101
2025-07-02 06:41:18.501
2025-07-02 06:41:18.501     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.501         r"""
2025-07-02 06:41:18.501         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.501         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.501         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.501         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.501
2025-07-02 06:41:18.501         Example:
2025-07-02 06:41:18.501
2025-07-02 06:41:18.501         >>> d = Differ()
2025-07-02 06:41:18.501         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.501         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.501         >>> print(''.join(results), end="")
2025-07-02 06:41:18.501         - abcDefghiJkl
2025-07-02 06:41:18.502         + abcdefGhijkl
2025-07-02 06:41:18.502         """
2025-07-02 06:41:18.502
2025-07-02 06:41:18.502         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.502         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.502         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.502         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.502         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.502
2025-07-02 06:41:18.502         # search for the pair that matches best without being identical
2025-07-02 06:41:18.502         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.502         # on junk -- unless we have to)
2025-07-02 06:41:18.502         for j in range(blo, bhi):
2025-07-02 06:41:18.502             bj = b[j]
2025-07-02 06:41:18.502             cruncher.set_seq2(bj)
2025-07-02 06:41:18.502             for i in range(alo, ahi):
2025-07-02 06:41:18.502                 ai = a[i]
2025-07-02 06:41:18.502                 if ai == bj:
2025-07-02 06:41:18.503                     if eqi is None:
2025-07-02 06:41:18.503                         eqi, eqj = i, j
2025-07-02 06:41:18.503                     continue
2025-07-02 06:41:18.503                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.503                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.503                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.503                 # compares by a factor of 3.
2025-07-02 06:41:18.503                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.503                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.503                 # of the computation is cached by cruncher
2025-07-02 06:41:18.503                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.503                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.503                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.503                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.503         if best_ratio < cutoff:
2025-07-02 06:41:18.503             # no non-identical "pretty close" pair
2025-07-02 06:41:18.503             if eqi is None:
2025-07-02 06:41:18.503                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.503                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.504                 return
2025-07-02 06:41:18.504             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.504             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.504         else:
2025-07-02 06:41:18.504             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.504             eqi = None
2025-07-02 06:41:18.504
2025-07-02 06:41:18.504         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.504         # identical
2025-07-02 06:41:18.504
2025-07-02 06:41:18.504         # pump out diffs from before the synch point
2025-07-02 06:41:18.504         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.504
2025-07-02 06:41:18.504         # do intraline marking on the synch pair
2025-07-02 06:41:18.504         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.504         if eqi is None:
2025-07-02 06:41:18.504             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.504             atags = btags = ""
2025-07-02 06:41:18.504             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.505             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.505                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.505                 if tag == 'replace':
2025-07-02 06:41:18.505                     atags += '^' * la
2025-07-02 06:41:18.505                     btags += '^' * lb
2025-07-02 06:41:18.505                 elif tag == 'delete':
2025-07-02 06:41:18.505                     atags += '-' * la
2025-07-02 06:41:18.505                 elif tag == 'insert':
2025-07-02 06:41:18.505                     btags += '+' * lb
2025-07-02 06:41:18.505                 elif tag == 'equal':
2025-07-02 06:41:18.505                     atags += ' ' * la
2025-07-02 06:41:18.505                     btags += ' ' * lb
2025-07-02 06:41:18.505                 else:
2025-07-02 06:41:18.505                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.505             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.505         else:
2025-07-02 06:41:18.505             # the synch pair is identical
2025-07-02 06:41:18.505             yield '  ' + aelt
2025-07-02 06:41:18.505
2025-07-02 06:41:18.506         # pump out diffs from after the synch point
2025-07-02 06:41:18.506 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.506
2025-07-02 06:41:18.506 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.506 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.506
2025-07-02 06:41:18.506 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.506 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.506 alo = 411, ahi = 1101
2025-07-02 06:41:18.506 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.506 blo = 411, bhi = 1101
2025-07-02 06:41:18.506
2025-07-02 06:41:18.506     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.506         g = []
2025-07-02 06:41:18.506         if alo < ahi:
2025-07-02 06:41:18.506             if blo < bhi:
2025-07-02 06:41:18.506                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.506             else:
2025-07-02 06:41:18.507                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.507         elif blo < bhi:
2025-07-02 06:41:18.507             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.507
2025-07-02 06:41:18.507 >       yield from g
2025-07-02 06:41:18.507
2025-07-02 06:41:18.507 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.507 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.507
2025-07-02 06:41:18.507 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.507 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.507 alo = 411, ahi = 1101
2025-07-02 06:41:18.507 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.507 blo = 411, bhi = 1101
2025-07-02 06:41:18.507
2025-07-02 06:41:18.507     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.507         r"""
2025-07-02 06:41:18.507         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.507         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.508         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.508         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.508
2025-07-02 06:41:18.508         Example:
2025-07-02 06:41:18.508
2025-07-02 06:41:18.508         >>> d = Differ()
2025-07-02 06:41:18.508         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.508         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.508         >>> print(''.join(results), end="")
2025-07-02 06:41:18.508         - abcDefghiJkl
2025-07-02 06:41:18.508         + abcdefGhijkl
2025-07-02 06:41:18.508         """
2025-07-02 06:41:18.508
2025-07-02 06:41:18.508         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.508         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.508         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.508         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.509         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.509
2025-07-02 06:41:18.509         # search for the pair that matches best without being identical
2025-07-02 06:41:18.509         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.509         # on junk -- unless we have to)
2025-07-02 06:41:18.509         for j in range(blo, bhi):
2025-07-02 06:41:18.509             bj = b[j]
2025-07-02 06:41:18.509             cruncher.set_seq2(bj)
2025-07-02 06:41:18.509             for i in range(alo, ahi):
2025-07-02 06:41:18.509                 ai = a[i]
2025-07-02 06:41:18.509                 if ai == bj:
2025-07-02 06:41:18.509                     if eqi is None:
2025-07-02 06:41:18.509                         eqi, eqj = i, j
2025-07-02 06:41:18.509                     continue
2025-07-02 06:41:18.509                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.509                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.509                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.509                 # compares by a factor of 3.
2025-07-02 06:41:18.509                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.510                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.510                 # of the computation is cached by cruncher
2025-07-02 06:41:18.510                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.510                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.510                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.510                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.510         if best_ratio < cutoff:
2025-07-02 06:41:18.510             # no non-identical "pretty close" pair
2025-07-02 06:41:18.510             if eqi is None:
2025-07-02 06:41:18.510                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.510                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.510                 return
2025-07-02 06:41:18.510             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.510             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.510         else:
2025-07-02 06:41:18.510             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.510             eqi = None
2025-07-02 06:41:18.510
2025-07-02 06:41:18.510         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.511         # identical
2025-07-02 06:41:18.511
2025-07-02 06:41:18.511         # pump out diffs from before the synch point
2025-07-02 06:41:18.511         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.511
2025-07-02 06:41:18.511         # do intraline marking on the synch pair
2025-07-02 06:41:18.511         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.511         if eqi is None:
2025-07-02 06:41:18.511             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.511             atags = btags = ""
2025-07-02 06:41:18.511             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.511             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.511                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.511                 if tag == 'replace':
2025-07-02 06:41:18.511                     atags += '^' * la
2025-07-02 06:41:18.511                     btags += '^' * lb
2025-07-02 06:41:18.511                 elif tag == 'delete':
2025-07-02 06:41:18.511                     atags += '-' * la
2025-07-02 06:41:18.511                 elif tag == 'insert':
2025-07-02 06:41:18.512                     btags += '+' * lb
2025-07-02 06:41:18.512                 elif tag == 'equal':
2025-07-02 06:41:18.512                     atags += ' ' * la
2025-07-02 06:41:18.512                     btags += ' ' * lb
2025-07-02 06:41:18.512                 else:
2025-07-02 06:41:18.512                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.512             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.512         else:
2025-07-02 06:41:18.512             # the synch pair is identical
2025-07-02 06:41:18.512             yield '  ' + aelt
2025-07-02 06:41:18.512
2025-07-02 06:41:18.512         # pump out diffs from after the synch point
2025-07-02 06:41:18.512 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.512
2025-07-02 06:41:18.512 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.512 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.512
2025-07-02 06:41:18.512 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.512 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.513 alo = 412, ahi = 1101
2025-07-02 06:41:18.513 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.513 blo = 412, bhi = 1101
2025-07-02 06:41:18.513
2025-07-02 06:41:18.513     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.513         g = []
2025-07-02 06:41:18.513         if alo < ahi:
2025-07-02 06:41:18.513             if blo < bhi:
2025-07-02 06:41:18.513                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.513             else:
2025-07-02 06:41:18.513                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.513         elif blo < bhi:
2025-07-02 06:41:18.513             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.513
2025-07-02 06:41:18.513 >       yield from g
2025-07-02 06:41:18.513
2025-07-02 06:41:18.513 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.513 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.513
2025-07-02 06:41:18.514 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.514 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.514 alo = 412, ahi = 1101
2025-07-02 06:41:18.514 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.514 blo = 412, bhi = 1101
2025-07-02 06:41:18.514
2025-07-02 06:41:18.514     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.514         r"""
2025-07-02 06:41:18.514         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.514         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.514         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.514         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.514
2025-07-02 06:41:18.514         Example:
2025-07-02 06:41:18.514
2025-07-02 06:41:18.514         >>> d = Differ()
2025-07-02 06:41:18.514         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.514         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.514         >>> print(''.join(results), end="")
2025-07-02 06:41:18.515         - abcDefghiJkl
2025-07-02 06:41:18.515         + abcdefGhijkl
2025-07-02 06:41:18.515         """
2025-07-02 06:41:18.515
2025-07-02 06:41:18.515         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.515         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.515         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.515         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.515         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.515
2025-07-02 06:41:18.515         # search for the pair that matches best without being identical
2025-07-02 06:41:18.515         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.515         # on junk -- unless we have to)
2025-07-02 06:41:18.515         for j in range(blo, bhi):
2025-07-02 06:41:18.515             bj = b[j]
2025-07-02 06:41:18.515             cruncher.set_seq2(bj)
2025-07-02 06:41:18.516             for i in range(alo, ahi):
2025-07-02 06:41:18.516                 ai = a[i]
2025-07-02 06:41:18.516                 if ai == bj:
2025-07-02 06:41:18.516                     if eqi is None:
2025-07-02 06:41:18.516                         eqi, eqj = i, j
2025-07-02 06:41:18.516                     continue
2025-07-02 06:41:18.516                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.516                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.516                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.516                 # compares by a factor of 3.
2025-07-02 06:41:18.516                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.516                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.516                 # of the computation is cached by cruncher
2025-07-02 06:41:18.516                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.516                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.516                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.516                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.517         if best_ratio < cutoff:
2025-07-02 06:41:18.517             # no non-identical "pretty close" pair
2025-07-02 06:41:18.517             if eqi is None:
2025-07-02 06:41:18.517                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.517                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.517                 return
2025-07-02 06:41:18.517             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.517             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.517         else:
2025-07-02 06:41:18.517             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.517             eqi = None
2025-07-02 06:41:18.517
2025-07-02 06:41:18.517         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.517         # identical
2025-07-02 06:41:18.517
2025-07-02 06:41:18.517         # pump out diffs from before the synch point
2025-07-02 06:41:18.517         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.517
2025-07-02 06:41:18.517         # do intraline marking on the synch pair
2025-07-02 06:41:18.518         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.518         if eqi is None:
2025-07-02 06:41:18.518             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.518             atags = btags = ""
2025-07-02 06:41:18.518             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.518             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.518                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.518                 if tag == 'replace':
2025-07-02 06:41:18.518                     atags += '^' * la
2025-07-02 06:41:18.518                     btags += '^' * lb
2025-07-02 06:41:18.518                 elif tag == 'delete':
2025-07-02 06:41:18.518                     atags += '-' * la
2025-07-02 06:41:18.518                 elif tag == 'insert':
2025-07-02 06:41:18.518                     btags += '+' * lb
2025-07-02 06:41:18.518                 elif tag == 'equal':
2025-07-02 06:41:18.518                     atags += ' ' * la
2025-07-02 06:41:18.518                     btags += ' ' * lb
2025-07-02 06:41:18.518                 else:
2025-07-02 06:41:18.519                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.519             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.519         else:
2025-07-02 06:41:18.519             # the synch pair is identical
2025-07-02 06:41:18.519             yield '  ' + aelt
2025-07-02 06:41:18.519
2025-07-02 06:41:18.519         # pump out diffs from after the synch point
2025-07-02 06:41:18.519 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.519
2025-07-02 06:41:18.519 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.519 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.519
2025-07-02 06:41:18.519 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.519 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.519 alo = 413, ahi = 1101
2025-07-02 06:41:18.519 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.519 blo = 413, bhi = 1101
2025-07-02 06:41:18.519
2025-07-02 06:41:18.519     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.520         g = []
2025-07-02 06:41:18.520         if alo < ahi:
2025-07-02 06:41:18.520             if blo < bhi:
2025-07-02 06:41:18.520                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.520             else:
2025-07-02 06:41:18.520                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.520         elif blo < bhi:
2025-07-02 06:41:18.520             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.520
2025-07-02 06:41:18.520 >       yield from g
2025-07-02 06:41:18.520
2025-07-02 06:41:18.520 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.520 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.520
2025-07-02 06:41:18.520 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.520 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.520 alo = 413, ahi = 1101
2025-07-02 06:41:18.520 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.521 blo = 413, bhi = 1101
2025-07-02 06:41:18.521
2025-07-02 06:41:18.521     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.521         r"""
2025-07-02 06:41:18.521         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.521         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.521         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.521         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.521
2025-07-02 06:41:18.521         Example:
2025-07-02 06:41:18.521
2025-07-02 06:41:18.521         >>> d = Differ()
2025-07-02 06:41:18.521         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.521         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.521         >>> print(''.join(results), end="")
2025-07-02 06:41:18.521         - abcDefghiJkl
2025-07-02 06:41:18.521         + abcdefGhijkl
2025-07-02 06:41:18.521         """
2025-07-02 06:41:18.522
2025-07-02 06:41:18.522         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.522         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.522         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.522         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.522         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.522
2025-07-02 06:41:18.522         # search for the pair that matches best without being identical
2025-07-02 06:41:18.522         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.522         # on junk -- unless we have to)
2025-07-02 06:41:18.522         for j in range(blo, bhi):
2025-07-02 06:41:18.522             bj = b[j]
2025-07-02 06:41:18.522             cruncher.set_seq2(bj)
2025-07-02 06:41:18.522             for i in range(alo, ahi):
2025-07-02 06:41:18.522                 ai = a[i]
2025-07-02 06:41:18.522                 if ai == bj:
2025-07-02 06:41:18.522                     if eqi is None:
2025-07-02 06:41:18.522                         eqi, eqj = i, j
2025-07-02 06:41:18.523                     continue
2025-07-02 06:41:18.523                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.523                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.523                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.523                 # compares by a factor of 3.
2025-07-02 06:41:18.523                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.523                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.523                 # of the computation is cached by cruncher
2025-07-02 06:41:18.523                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.523                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.523                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.523                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.523         if best_ratio < cutoff:
2025-07-02 06:41:18.523             # no non-identical "pretty close" pair
2025-07-02 06:41:18.523             if eqi is None:
2025-07-02 06:41:18.523                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.523                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.523                 return
2025-07-02 06:41:18.523             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.524             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.524         else:
2025-07-02 06:41:18.524             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.524             eqi = None
2025-07-02 06:41:18.524
2025-07-02 06:41:18.524         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.524         # identical
2025-07-02 06:41:18.524
2025-07-02 06:41:18.524         # pump out diffs from before the synch point
2025-07-02 06:41:18.524         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.524
2025-07-02 06:41:18.524         # do intraline marking on the synch pair
2025-07-02 06:41:18.524         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.524         if eqi is None:
2025-07-02 06:41:18.524             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.524             atags = btags = ""
2025-07-02 06:41:18.524             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.524             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.524                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.525                 if tag == 'replace':
2025-07-02 06:41:18.525                     atags += '^' * la
2025-07-02 06:41:18.525                     btags += '^' * lb
2025-07-02 06:41:18.525                 elif tag == 'delete':
2025-07-02 06:41:18.525                     atags += '-' * la
2025-07-02 06:41:18.525                 elif tag == 'insert':
2025-07-02 06:41:18.525                     btags += '+' * lb
2025-07-02 06:41:18.525                 elif tag == 'equal':
2025-07-02 06:41:18.525                     atags += ' ' * la
2025-07-02 06:41:18.525                     btags += ' ' * lb
2025-07-02 06:41:18.525                 else:
2025-07-02 06:41:18.525                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.525             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.525         else:
2025-07-02 06:41:18.525             # the synch pair is identical
2025-07-02 06:41:18.525             yield '  ' + aelt
2025-07-02 06:41:18.525
2025-07-02 06:41:18.525         # pump out diffs from after the synch point
2025-07-02 06:41:18.525 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.526
2025-07-02 06:41:18.526 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.526 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.526
2025-07-02 06:41:18.526 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.526 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.526 alo = 414, ahi = 1101
2025-07-02 06:41:18.526 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.526 blo = 414, bhi = 1101
2025-07-02 06:41:18.526
2025-07-02 06:41:18.526     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.526         g = []
2025-07-02 06:41:18.526         if alo < ahi:
2025-07-02 06:41:18.526             if blo < bhi:
2025-07-02 06:41:18.526                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.526             else:
2025-07-02 06:41:18.526                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.526         elif blo < bhi:
2025-07-02 06:41:18.527             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.527
2025-07-02 06:41:18.527 >       yield from g
2025-07-02 06:41:18.527
2025-07-02 06:41:18.527 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.527 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.527
2025-07-02 06:41:18.527 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.527 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.527 alo = 414, ahi = 1101
2025-07-02 06:41:18.527 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.527 blo = 414, bhi = 1101
2025-07-02 06:41:18.527
2025-07-02 06:41:18.527     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.527         r"""
2025-07-02 06:41:18.527         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.527         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.527         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.527         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.528
2025-07-02 06:41:18.528         Example:
2025-07-02 06:41:18.528
2025-07-02 06:41:18.528         >>> d = Differ()
2025-07-02 06:41:18.528         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.528         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.528         >>> print(''.join(results), end="")
2025-07-02 06:41:18.528         - abcDefghiJkl
2025-07-02 06:41:18.528         + abcdefGhijkl
2025-07-02 06:41:18.528         """
2025-07-02 06:41:18.528
2025-07-02 06:41:18.528         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.528         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.528         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.528         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.528         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.528
2025-07-02 06:41:18.529         # search for the pair that matches best without being identical
2025-07-02 06:41:18.529         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.529         # on junk -- unless we have to)
2025-07-02 06:41:18.529         for j in range(blo, bhi):
2025-07-02 06:41:18.529             bj = b[j]
2025-07-02 06:41:18.529             cruncher.set_seq2(bj)
2025-07-02 06:41:18.529             for i in range(alo, ahi):
2025-07-02 06:41:18.529                 ai = a[i]
2025-07-02 06:41:18.529                 if ai == bj:
2025-07-02 06:41:18.529                     if eqi is None:
2025-07-02 06:41:18.529                         eqi, eqj = i, j
2025-07-02 06:41:18.529                     continue
2025-07-02 06:41:18.529                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.529                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.529                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.529                 # compares by a factor of 3.
2025-07-02 06:41:18.529                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.529                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.529                 # of the computation is cached by cruncher
2025-07-02 06:41:18.530                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.530                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.530                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.530                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.530         if best_ratio < cutoff:
2025-07-02 06:41:18.530             # no non-identical "pretty close" pair
2025-07-02 06:41:18.530             if eqi is None:
2025-07-02 06:41:18.530                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.530                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.530                 return
2025-07-02 06:41:18.530             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.530             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.530         else:
2025-07-02 06:41:18.530             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.530             eqi = None
2025-07-02 06:41:18.530
2025-07-02 06:41:18.530         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.530         # identical
2025-07-02 06:41:18.530
2025-07-02 06:41:18.531         # pump out diffs from before the synch point
2025-07-02 06:41:18.531         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.531
2025-07-02 06:41:18.531         # do intraline marking on the synch pair
2025-07-02 06:41:18.531         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.531         if eqi is None:
2025-07-02 06:41:18.531             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.531             atags = btags = ""
2025-07-02 06:41:18.531             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.531             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.531                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.531                 if tag == 'replace':
2025-07-02 06:41:18.531                     atags += '^' * la
2025-07-02 06:41:18.531                     btags += '^' * lb
2025-07-02 06:41:18.531                 elif tag == 'delete':
2025-07-02 06:41:18.531                     atags += '-' * la
2025-07-02 06:41:18.531                 elif tag == 'insert':
2025-07-02 06:41:18.531                     btags += '+' * lb
2025-07-02 06:41:18.532                 elif tag == 'equal':
2025-07-02 06:41:18.532                     atags += ' ' * la
2025-07-02 06:41:18.532                     btags += ' ' * lb
2025-07-02 06:41:18.532                 else:
2025-07-02 06:41:18.532                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.532             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.532         else:
2025-07-02 06:41:18.532             # the synch pair is identical
2025-07-02 06:41:18.532             yield '  ' + aelt
2025-07-02 06:41:18.532
2025-07-02 06:41:18.532         # pump out diffs from after the synch point
2025-07-02 06:41:18.532 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.532
2025-07-02 06:41:18.532 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.532 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.532
2025-07-02 06:41:18.532 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.532 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.532 alo = 415, ahi = 1101
2025-07-02 06:41:18.533 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.533 blo = 415, bhi = 1101
2025-07-02 06:41:18.533
2025-07-02 06:41:18.533     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.533         g = []
2025-07-02 06:41:18.533         if alo < ahi:
2025-07-02 06:41:18.533             if blo < bhi:
2025-07-02 06:41:18.533                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.533             else:
2025-07-02 06:41:18.533                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.533         elif blo < bhi:
2025-07-02 06:41:18.533             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.533
2025-07-02 06:41:18.533 >       yield from g
2025-07-02 06:41:18.533
2025-07-02 06:41:18.533 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.533 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.533
2025-07-02 06:41:18.533 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.533 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.534 alo = 415, ahi = 1101
2025-07-02 06:41:18.534 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.534 blo = 415, bhi = 1101
2025-07-02 06:41:18.534
2025-07-02 06:41:18.534     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.534         r"""
2025-07-02 06:41:18.534         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.534         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.534         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.534         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.534
2025-07-02 06:41:18.534         Example:
2025-07-02 06:41:18.534
2025-07-02 06:41:18.534         >>> d = Differ()
2025-07-02 06:41:18.534         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.534         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.534         >>> print(''.join(results), end="")
2025-07-02 06:41:18.535         - abcDefghiJkl
2025-07-02 06:41:18.535         + abcdefGhijkl
2025-07-02 06:41:18.535         """
2025-07-02 06:41:18.535
2025-07-02 06:41:18.535         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.535         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.535         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.535         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.535         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.535
2025-07-02 06:41:18.535         # search for the pair that matches best without being identical
2025-07-02 06:41:18.535         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.535         # on junk -- unless we have to)
2025-07-02 06:41:18.535         for j in range(blo, bhi):
2025-07-02 06:41:18.535             bj = b[j]
2025-07-02 06:41:18.535             cruncher.set_seq2(bj)
2025-07-02 06:41:18.535             for i in range(alo, ahi):
2025-07-02 06:41:18.536                 ai = a[i]
2025-07-02 06:41:18.536                 if ai == bj:
2025-07-02 06:41:18.536                     if eqi is None:
2025-07-02 06:41:18.536                         eqi, eqj = i, j
2025-07-02 06:41:18.536                     continue
2025-07-02 06:41:18.536                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.536                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.536                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.536                 # compares by a factor of 3.
2025-07-02 06:41:18.536                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.536                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.536                 # of the computation is cached by cruncher
2025-07-02 06:41:18.536                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.536                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.536                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.536                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.536         if best_ratio < cutoff:
2025-07-02 06:41:18.536             # no non-identical "pretty close" pair
2025-07-02 06:41:18.537             if eqi is None:
2025-07-02 06:41:18.537                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.537                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.537                 return
2025-07-02 06:41:18.537             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.537             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.537         else:
2025-07-02 06:41:18.537             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.537             eqi = None
2025-07-02 06:41:18.537
2025-07-02 06:41:18.537         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.537         # identical
2025-07-02 06:41:18.537
2025-07-02 06:41:18.537         # pump out diffs from before the synch point
2025-07-02 06:41:18.537         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.537
2025-07-02 06:41:18.537         # do intraline marking on the synch pair
2025-07-02 06:41:18.537         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.537         if eqi is None:
2025-07-02 06:41:18.538             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.538             atags = btags = ""
2025-07-02 06:41:18.538             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.538             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.538                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.538                 if tag == 'replace':
2025-07-02 06:41:18.538                     atags += '^' * la
2025-07-02 06:41:18.538                     btags += '^' * lb
2025-07-02 06:41:18.538                 elif tag == 'delete':
2025-07-02 06:41:18.538                     atags += '-' * la
2025-07-02 06:41:18.538                 elif tag == 'insert':
2025-07-02 06:41:18.538                     btags += '+' * lb
2025-07-02 06:41:18.538                 elif tag == 'equal':
2025-07-02 06:41:18.538                     atags += ' ' * la
2025-07-02 06:41:18.538                     btags += ' ' * lb
2025-07-02 06:41:18.538                 else:
2025-07-02 06:41:18.538                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.538             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.538         else:
2025-07-02 06:41:18.538             # the synch pair is identical
2025-07-02 06:41:18.539             yield '  ' + aelt
2025-07-02 06:41:18.539
2025-07-02 06:41:18.539         # pump out diffs from after the synch point
2025-07-02 06:41:18.539 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.539
2025-07-02 06:41:18.539 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.539 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.539
2025-07-02 06:41:18.539 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.539 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.539 alo = 416, ahi = 1101
2025-07-02 06:41:18.539 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.539 blo = 416, bhi = 1101
2025-07-02 06:41:18.539
2025-07-02 06:41:18.539     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.539         g = []
2025-07-02 06:41:18.539         if alo < ahi:
2025-07-02 06:41:18.539             if blo < bhi:
2025-07-02 06:41:18.540                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.540             else:
2025-07-02 06:41:18.540                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.540         elif blo < bhi:
2025-07-02 06:41:18.540             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.540
2025-07-02 06:41:18.540 >       yield from g
2025-07-02 06:41:18.540
2025-07-02 06:41:18.540 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.540 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.540
2025-07-02 06:41:18.540 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.540 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.540 alo = 416, ahi = 1101
2025-07-02 06:41:18.540 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.540 blo = 416, bhi = 1101
2025-07-02 06:41:18.540
2025-07-02 06:41:18.540     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.540         r"""
2025-07-02 06:41:18.541         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.541         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.541         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.541         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.541
2025-07-02 06:41:18.541         Example:
2025-07-02 06:41:18.541
2025-07-02 06:41:18.541         >>> d = Differ()
2025-07-02 06:41:18.541         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.541         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.541         >>> print(''.join(results), end="")
2025-07-02 06:41:18.541         - abcDefghiJkl
2025-07-02 06:41:18.541         + abcdefGhijkl
2025-07-02 06:41:18.541         """
2025-07-02 06:41:18.541
2025-07-02 06:41:18.541         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.541         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.542         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.542         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.542         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.542
2025-07-02 06:41:18.542         # search for the pair that matches best without being identical
2025-07-02 06:41:18.542         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.542         # on junk -- unless we have to)
2025-07-02 06:41:18.542         for j in range(blo, bhi):
2025-07-02 06:41:18.542             bj = b[j]
2025-07-02 06:41:18.542             cruncher.set_seq2(bj)
2025-07-02 06:41:18.542             for i in range(alo, ahi):
2025-07-02 06:41:18.542                 ai = a[i]
2025-07-02 06:41:18.542                 if ai == bj:
2025-07-02 06:41:18.542                     if eqi is None:
2025-07-02 06:41:18.542                         eqi, eqj = i, j
2025-07-02 06:41:18.542                     continue
2025-07-02 06:41:18.542                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.542                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.542                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.543                 # compares by a factor of 3.
2025-07-02 06:41:18.543                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.543                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.543                 # of the computation is cached by cruncher
2025-07-02 06:41:18.543                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.543                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.543                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.543                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.543         if best_ratio < cutoff:
2025-07-02 06:41:18.543             # no non-identical "pretty close" pair
2025-07-02 06:41:18.543             if eqi is None:
2025-07-02 06:41:18.543                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.543                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.543                 return
2025-07-02 06:41:18.543             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.543             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.543         else:
2025-07-02 06:41:18.543             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.544             eqi = None
2025-07-02 06:41:18.544
2025-07-02 06:41:18.544         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.544         # identical
2025-07-02 06:41:18.544
2025-07-02 06:41:18.544         # pump out diffs from before the synch point
2025-07-02 06:41:18.544         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.544
2025-07-02 06:41:18.544         # do intraline marking on the synch pair
2025-07-02 06:41:18.544         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.544         if eqi is None:
2025-07-02 06:41:18.544             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.544             atags = btags = ""
2025-07-02 06:41:18.544             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.544             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.544                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.544                 if tag == 'replace':
2025-07-02 06:41:18.544                     atags += '^' * la
2025-07-02 06:41:18.544                     btags += '^' * lb
2025-07-02 06:41:18.545                 elif tag == 'delete':
2025-07-02 06:41:18.545                     atags += '-' * la
2025-07-02 06:41:18.545                 elif tag == 'insert':
2025-07-02 06:41:18.545                     btags += '+' * lb
2025-07-02 06:41:18.545                 elif tag == 'equal':
2025-07-02 06:41:18.545                     atags += ' ' * la
2025-07-02 06:41:18.545                     btags += ' ' * lb
2025-07-02 06:41:18.545                 else:
2025-07-02 06:41:18.545                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.545             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.545         else:
2025-07-02 06:41:18.545             # the synch pair is identical
2025-07-02 06:41:18.545             yield '  ' + aelt
2025-07-02 06:41:18.545
2025-07-02 06:41:18.545         # pump out diffs from after the synch point
2025-07-02 06:41:18.545 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.545
2025-07-02 06:41:18.545 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.545 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.546
2025-07-02 06:41:18.546 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.546 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.546 alo = 417, ahi = 1101
2025-07-02 06:41:18.546 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.546 blo = 417, bhi = 1101
2025-07-02 06:41:18.546
2025-07-02 06:41:18.546     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.546         g = []
2025-07-02 06:41:18.546         if alo < ahi:
2025-07-02 06:41:18.546             if blo < bhi:
2025-07-02 06:41:18.546                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.546             else:
2025-07-02 06:41:18.546                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.546         elif blo < bhi:
2025-07-02 06:41:18.546             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.546
2025-07-02 06:41:18.546 >       yield from g
2025-07-02 06:41:18.546
2025-07-02 06:41:18.547 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.547 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.547
2025-07-02 06:41:18.547 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.547 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.547 alo = 417, ahi = 1101
2025-07-02 06:41:18.547 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.547 blo = 417, bhi = 1101
2025-07-02 06:41:18.547
2025-07-02 06:41:18.547     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.547         r"""
2025-07-02 06:41:18.547         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.547         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.547         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.547         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.547
2025-07-02 06:41:18.547         Example:
2025-07-02 06:41:18.547
2025-07-02 06:41:18.548         >>> d = Differ()
2025-07-02 06:41:18.548         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.548         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.548         >>> print(''.join(results), end="")
2025-07-02 06:41:18.548         - abcDefghiJkl
2025-07-02 06:41:18.548         + abcdefGhijkl
2025-07-02 06:41:18.548         """
2025-07-02 06:41:18.548
2025-07-02 06:41:18.548         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.548         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.548         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.548         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.548         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.548
2025-07-02 06:41:18.548         # search for the pair that matches best without being identical
2025-07-02 06:41:18.548         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.548         # on junk -- unless we have to)
2025-07-02 06:41:18.549         for j in range(blo, bhi):
2025-07-02 06:41:18.549             bj = b[j]
2025-07-02 06:41:18.549             cruncher.set_seq2(bj)
2025-07-02 06:41:18.549             for i in range(alo, ahi):
2025-07-02 06:41:18.549                 ai = a[i]
2025-07-02 06:41:18.549                 if ai == bj:
2025-07-02 06:41:18.549                     if eqi is None:
2025-07-02 06:41:18.549                         eqi, eqj = i, j
2025-07-02 06:41:18.549                     continue
2025-07-02 06:41:18.549                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.549                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.549                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.549                 # compares by a factor of 3.
2025-07-02 06:41:18.549                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.549                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.549                 # of the computation is cached by cruncher
2025-07-02 06:41:18.549                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.549                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.549                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.549                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.550         if best_ratio < cutoff:
2025-07-02 06:41:18.550             # no non-identical "pretty close" pair
2025-07-02 06:41:18.550             if eqi is None:
2025-07-02 06:41:18.550                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.550                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.550                 return
2025-07-02 06:41:18.550             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.550             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.550         else:
2025-07-02 06:41:18.550             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.550             eqi = None
2025-07-02 06:41:18.550
2025-07-02 06:41:18.550         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.550         # identical
2025-07-02 06:41:18.550
2025-07-02 06:41:18.550         # pump out diffs from before the synch point
2025-07-02 06:41:18.550         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.550
2025-07-02 06:41:18.550         # do intraline marking on the synch pair
2025-07-02 06:41:18.551         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.551         if eqi is None:
2025-07-02 06:41:18.551             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.551             atags = btags = ""
2025-07-02 06:41:18.551             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.551             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.551                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.551                 if tag == 'replace':
2025-07-02 06:41:18.551                     atags += '^' * la
2025-07-02 06:41:18.551                     btags += '^' * lb
2025-07-02 06:41:18.551                 elif tag == 'delete':
2025-07-02 06:41:18.551                     atags += '-' * la
2025-07-02 06:41:18.551                 elif tag == 'insert':
2025-07-02 06:41:18.551                     btags += '+' * lb
2025-07-02 06:41:18.551                 elif tag == 'equal':
2025-07-02 06:41:18.551                     atags += ' ' * la
2025-07-02 06:41:18.551                     btags += ' ' * lb
2025-07-02 06:41:18.551                 else:
2025-07-02 06:41:18.551                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.551             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.552         else:
2025-07-02 06:41:18.552             # the synch pair is identical
2025-07-02 06:41:18.552             yield '  ' + aelt
2025-07-02 06:41:18.552
2025-07-02 06:41:18.552         # pump out diffs from after the synch point
2025-07-02 06:41:18.552 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.552
2025-07-02 06:41:18.552 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.552 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.552
2025-07-02 06:41:18.552 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.552 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.552 alo = 418, ahi = 1101
2025-07-02 06:41:18.552 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.552 blo = 418, bhi = 1101
2025-07-02 06:41:18.552
2025-07-02 06:41:18.552     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.553         g = []
2025-07-02 06:41:18.553         if alo < ahi:
2025-07-02 06:41:18.553             if blo < bhi:
2025-07-02 06:41:18.553                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.553             else:
2025-07-02 06:41:18.553                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.553         elif blo < bhi:
2025-07-02 06:41:18.553             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.553
2025-07-02 06:41:18.553 >       yield from g
2025-07-02 06:41:18.553
2025-07-02 06:41:18.553 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.553 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.553
2025-07-02 06:41:18.553 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.553 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.553 alo = 418, ahi = 1101
2025-07-02 06:41:18.553 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.553 blo = 418, bhi = 1101
2025-07-02 06:41:18.554
2025-07-02 06:41:18.554     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.554         r"""
2025-07-02 06:41:18.554         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.554         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.554         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.554         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.554
2025-07-02 06:41:18.554         Example:
2025-07-02 06:41:18.554
2025-07-02 06:41:18.554         >>> d = Differ()
2025-07-02 06:41:18.554         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.554         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.554         >>> print(''.join(results), end="")
2025-07-02 06:41:18.554         - abcDefghiJkl
2025-07-02 06:41:18.554         + abcdefGhijkl
2025-07-02 06:41:18.554         """
2025-07-02 06:41:18.555
2025-07-02 06:41:18.555         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.555         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.555         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.555         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.555         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.555
2025-07-02 06:41:18.555         # search for the pair that matches best without being identical
2025-07-02 06:41:18.555         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.555         # on junk -- unless we have to)
2025-07-02 06:41:18.555         for j in range(blo, bhi):
2025-07-02 06:41:18.555             bj = b[j]
2025-07-02 06:41:18.555             cruncher.set_seq2(bj)
2025-07-02 06:41:18.555             for i in range(alo, ahi):
2025-07-02 06:41:18.555                 ai = a[i]
2025-07-02 06:41:18.555                 if ai == bj:
2025-07-02 06:41:18.555                     if eqi is None:
2025-07-02 06:41:18.555                         eqi, eqj = i, j
2025-07-02 06:41:18.555                     continue
2025-07-02 06:41:18.556                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.556                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.556                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.556                 # compares by a factor of 3.
2025-07-02 06:41:18.556                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.556                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.556                 # of the computation is cached by cruncher
2025-07-02 06:41:18.556                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.556                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.556                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.556                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.556         if best_ratio < cutoff:
2025-07-02 06:41:18.556             # no non-identical "pretty close" pair
2025-07-02 06:41:18.556             if eqi is None:
2025-07-02 06:41:18.556                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.556                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.556                 return
2025-07-02 06:41:18.556             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.556             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.557         else:
2025-07-02 06:41:18.557             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.557             eqi = None
2025-07-02 06:41:18.557
2025-07-02 06:41:18.557         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.557         # identical
2025-07-02 06:41:18.557
2025-07-02 06:41:18.557         # pump out diffs from before the synch point
2025-07-02 06:41:18.557         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.557
2025-07-02 06:41:18.557         # do intraline marking on the synch pair
2025-07-02 06:41:18.557         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.557         if eqi is None:
2025-07-02 06:41:18.557             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.557             atags = btags = ""
2025-07-02 06:41:18.557             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.557             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.557                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.557                 if tag == 'replace':
2025-07-02 06:41:18.558                     atags += '^' * la
2025-07-02 06:41:18.558                     btags += '^' * lb
2025-07-02 06:41:18.558                 elif tag == 'delete':
2025-07-02 06:41:18.558                     atags += '-' * la
2025-07-02 06:41:18.558                 elif tag == 'insert':
2025-07-02 06:41:18.558                     btags += '+' * lb
2025-07-02 06:41:18.558                 elif tag == 'equal':
2025-07-02 06:41:18.558                     atags += ' ' * la
2025-07-02 06:41:18.558                     btags += ' ' * lb
2025-07-02 06:41:18.558                 else:
2025-07-02 06:41:18.558                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.558             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.558         else:
2025-07-02 06:41:18.558             # the synch pair is identical
2025-07-02 06:41:18.558             yield '  ' + aelt
2025-07-02 06:41:18.558
2025-07-02 06:41:18.558         # pump out diffs from after the synch point
2025-07-02 06:41:18.558 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.558
2025-07-02 06:41:18.559 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.559 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.559
2025-07-02 06:41:18.559 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.559 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.559 alo = 419, ahi = 1101
2025-07-02 06:41:18.559 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.559 blo = 419, bhi = 1101
2025-07-02 06:41:18.559
2025-07-02 06:41:18.559     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.559         g = []
2025-07-02 06:41:18.559         if alo < ahi:
2025-07-02 06:41:18.559             if blo < bhi:
2025-07-02 06:41:18.559                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.559             else:
2025-07-02 06:41:18.559                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.559         elif blo < bhi:
2025-07-02 06:41:18.559             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.559
2025-07-02 06:41:18.560 >       yield from g
2025-07-02 06:41:18.560
2025-07-02 06:41:18.560 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.560 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.560
2025-07-02 06:41:18.560 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.560 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.560 alo = 419, ahi = 1101
2025-07-02 06:41:18.560 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.560 blo = 419, bhi = 1101
2025-07-02 06:41:18.560
2025-07-02 06:41:18.560     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.560         r"""
2025-07-02 06:41:18.560         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.560         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.560         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.560         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.560
2025-07-02 06:41:18.560         Example:
2025-07-02 06:41:18.561
2025-07-02 06:41:18.561         >>> d = Differ()
2025-07-02 06:41:18.561         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.561         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.561         >>> print(''.join(results), end="")
2025-07-02 06:41:18.561         - abcDefghiJkl
2025-07-02 06:41:18.561         + abcdefGhijkl
2025-07-02 06:41:18.561         """
2025-07-02 06:41:18.561
2025-07-02 06:41:18.561         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.561         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.561         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.561         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.561         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.561
2025-07-02 06:41:18.561         # search for the pair that matches best without being identical
2025-07-02 06:41:18.562         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.562         # on junk -- unless we have to)
2025-07-02 06:41:18.562         for j in range(blo, bhi):
2025-07-02 06:41:18.562             bj = b[j]
2025-07-02 06:41:18.562             cruncher.set_seq2(bj)
2025-07-02 06:41:18.562             for i in range(alo, ahi):
2025-07-02 06:41:18.562                 ai = a[i]
2025-07-02 06:41:18.562                 if ai == bj:
2025-07-02 06:41:18.562                     if eqi is None:
2025-07-02 06:41:18.562                         eqi, eqj = i, j
2025-07-02 06:41:18.562                     continue
2025-07-02 06:41:18.562                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.562                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.562                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.562                 # compares by a factor of 3.
2025-07-02 06:41:18.562                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.562                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.562                 # of the computation is cached by cruncher
2025-07-02 06:41:18.562                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.563                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.563                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.563                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.563         if best_ratio < cutoff:
2025-07-02 06:41:18.563             # no non-identical "pretty close" pair
2025-07-02 06:41:18.563             if eqi is None:
2025-07-02 06:41:18.563                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.564                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.564                 return
2025-07-02 06:41:18.564             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.564             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.564         else:
2025-07-02 06:41:18.564             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.564             eqi = None
2025-07-02 06:41:18.564
2025-07-02 06:41:18.564         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.564         # identical
2025-07-02 06:41:18.564
2025-07-02 06:41:18.564         # pump out diffs from before the synch point
2025-07-02 06:41:18.564         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.564
2025-07-02 06:41:18.564         # do intraline marking on the synch pair
2025-07-02 06:41:18.564         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.564         if eqi is None:
2025-07-02 06:41:18.565             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.565             atags = btags = ""
2025-07-02 06:41:18.565             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.565             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.565                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.565                 if tag == 'replace':
2025-07-02 06:41:18.565                     atags += '^' * la
2025-07-02 06:41:18.565                     btags += '^' * lb
2025-07-02 06:41:18.565                 elif tag == 'delete':
2025-07-02 06:41:18.565                     atags += '-' * la
2025-07-02 06:41:18.565                 elif tag == 'insert':
2025-07-02 06:41:18.565                     btags += '+' * lb
2025-07-02 06:41:18.565                 elif tag == 'equal':
2025-07-02 06:41:18.565                     atags += ' ' * la
2025-07-02 06:41:18.565                     btags += ' ' * lb
2025-07-02 06:41:18.565                 else:
2025-07-02 06:41:18.565                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.566             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.566         else:
2025-07-02 06:41:18.566             # the synch pair is identical
2025-07-02 06:41:18.566             yield '  ' + aelt
2025-07-02 06:41:18.566
2025-07-02 06:41:18.566         # pump out diffs from after the synch point
2025-07-02 06:41:18.566 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.566
2025-07-02 06:41:18.566 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.566 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.566
2025-07-02 06:41:18.566 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.566 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.566 alo = 422, ahi = 1101
2025-07-02 06:41:18.566 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.566 blo = 422, bhi = 1101
2025-07-02 06:41:18.566
2025-07-02 06:41:18.566     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.566         g = []
2025-07-02 06:41:18.566         if alo < ahi:
2025-07-02 06:41:18.566             if blo < bhi:
2025-07-02 06:41:18.566                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.566             else:
2025-07-02 06:41:18.566                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.566         elif blo < bhi:
2025-07-02 06:41:18.567             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.567
2025-07-02 06:41:18.567 >       yield from g
2025-07-02 06:41:18.567
2025-07-02 06:41:18.567 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.567 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.567
2025-07-02 06:41:18.567 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.567 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.567 alo = 422, ahi = 1101
2025-07-02 06:41:18.567 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.567 blo = 422, bhi = 1101
2025-07-02 06:41:18.567
2025-07-02 06:41:18.567     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.567         r"""
2025-07-02 06:41:18.567         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.567         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.567         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.567         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.568
2025-07-02 06:41:18.568         Example:
2025-07-02 06:41:18.568
2025-07-02 06:41:18.568         >>> d = Differ()
2025-07-02 06:41:18.568         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.568         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.568         >>> print(''.join(results), end="")
2025-07-02 06:41:18.568         - abcDefghiJkl
2025-07-02 06:41:18.568         + abcdefGhijkl
2025-07-02 06:41:18.568         """
2025-07-02 06:41:18.568
2025-07-02 06:41:18.568         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.568         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.568         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.568         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.568         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.568
2025-07-02 06:41:18.568         # search for the pair that matches best without being identical
2025-07-02 06:41:18.569         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.569         # on junk -- unless we have to)
2025-07-02 06:41:18.569         for j in range(blo, bhi):
2025-07-02 06:41:18.569             bj = b[j]
2025-07-02 06:41:18.569             cruncher.set_seq2(bj)
2025-07-02 06:41:18.569             for i in range(alo, ahi):
2025-07-02 06:41:18.569                 ai = a[i]
2025-07-02 06:41:18.569                 if ai == bj:
2025-07-02 06:41:18.569                     if eqi is None:
2025-07-02 06:41:18.569                         eqi, eqj = i, j
2025-07-02 06:41:18.569                     continue
2025-07-02 06:41:18.569                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.569                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.569                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.569                 # compares by a factor of 3.
2025-07-02 06:41:18.569                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.569                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.569                 # of the computation is cached by cruncher
2025-07-02 06:41:18.569                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.570                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.570                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.570                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.570         if best_ratio < cutoff:
2025-07-02 06:41:18.570             # no non-identical "pretty close" pair
2025-07-02 06:41:18.570             if eqi is None:
2025-07-02 06:41:18.570                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.570                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.570                 return
2025-07-02 06:41:18.570             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.570             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.570         else:
2025-07-02 06:41:18.570             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.570             eqi = None
2025-07-02 06:41:18.570
2025-07-02 06:41:18.570         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.570         # identical
2025-07-02 06:41:18.570
2025-07-02 06:41:18.570         # pump out diffs from before the synch point
2025-07-02 06:41:18.570         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.571
2025-07-02 06:41:18.571         # do intraline marking on the synch pair
2025-07-02 06:41:18.571         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.571         if eqi is None:
2025-07-02 06:41:18.571             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.571             atags = btags = ""
2025-07-02 06:41:18.571             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.571             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.571                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.571                 if tag == 'replace':
2025-07-02 06:41:18.571                     atags += '^' * la
2025-07-02 06:41:18.571                     btags += '^' * lb
2025-07-02 06:41:18.571                 elif tag == 'delete':
2025-07-02 06:41:18.571                     atags += '-' * la
2025-07-02 06:41:18.571                 elif tag == 'insert':
2025-07-02 06:41:18.571                     btags += '+' * lb
2025-07-02 06:41:18.571                 elif tag == 'equal':
2025-07-02 06:41:18.571                     atags += ' ' * la
2025-07-02 06:41:18.572                     btags += ' ' * lb
2025-07-02 06:41:18.572                 else:
2025-07-02 06:41:18.572                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.572             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.572         else:
2025-07-02 06:41:18.572             # the synch pair is identical
2025-07-02 06:41:18.572             yield '  ' + aelt
2025-07-02 06:41:18.572
2025-07-02 06:41:18.572         # pump out diffs from after the synch point
2025-07-02 06:41:18.572 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.572
2025-07-02 06:41:18.572 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.572 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.572
2025-07-02 06:41:18.572 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.572 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.572 alo = 423, ahi = 1101
2025-07-02 06:41:18.572 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.572 blo = 423, bhi = 1101
2025-07-02 06:41:18.573
2025-07-02 06:41:18.573     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.573         g = []
2025-07-02 06:41:18.573         if alo < ahi:
2025-07-02 06:41:18.573             if blo < bhi:
2025-07-02 06:41:18.573                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.573             else:
2025-07-02 06:41:18.573                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.573         elif blo < bhi:
2025-07-02 06:41:18.573             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.573
2025-07-02 06:41:18.573 >       yield from g
2025-07-02 06:41:18.573
2025-07-02 06:41:18.573 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.573 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.573
2025-07-02 06:41:18.573 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.573 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.573 alo = 423, ahi = 1101
2025-07-02 06:41:18.574 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.574 blo = 423, bhi = 1101
2025-07-02 06:41:18.574
2025-07-02 06:41:18.574     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.574         r"""
2025-07-02 06:41:18.574         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.574         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.574         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.574         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.574
2025-07-02 06:41:18.574         Example:
2025-07-02 06:41:18.574
2025-07-02 06:41:18.574         >>> d = Differ()
2025-07-02 06:41:18.574         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.574         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.574         >>> print(''.join(results), end="")
2025-07-02 06:41:18.574         - abcDefghiJkl
2025-07-02 06:41:18.574         + abcdefGhijkl
2025-07-02 06:41:18.575         """
2025-07-02 06:41:18.575
2025-07-02 06:41:18.575         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.575         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.575         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.575         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.575         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.575
2025-07-02 06:41:18.575         # search for the pair that matches best without being identical
2025-07-02 06:41:18.575         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.575         # on junk -- unless we have to)
2025-07-02 06:41:18.575         for j in range(blo, bhi):
2025-07-02 06:41:18.575             bj = b[j]
2025-07-02 06:41:18.575             cruncher.set_seq2(bj)
2025-07-02 06:41:18.575             for i in range(alo, ahi):
2025-07-02 06:41:18.575                 ai = a[i]
2025-07-02 06:41:18.575                 if ai == bj:
2025-07-02 06:41:18.575                     if eqi is None:
2025-07-02 06:41:18.575                         eqi, eqj = i, j
2025-07-02 06:41:18.576                     continue
2025-07-02 06:41:18.576                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.576                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.576                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.576                 # compares by a factor of 3.
2025-07-02 06:41:18.576                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.576                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.576                 # of the computation is cached by cruncher
2025-07-02 06:41:18.576                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.576                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.576                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.576                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.576         if best_ratio < cutoff:
2025-07-02 06:41:18.576             # no non-identical "pretty close" pair
2025-07-02 06:41:18.576             if eqi is None:
2025-07-02 06:41:18.576                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.576                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.576                 return
2025-07-02 06:41:18.576             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.576             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.577         else:
2025-07-02 06:41:18.577             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.577             eqi = None
2025-07-02 06:41:18.577
2025-07-02 06:41:18.577         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.577         # identical
2025-07-02 06:41:18.577
2025-07-02 06:41:18.577         # pump out diffs from before the synch point
2025-07-02 06:41:18.577         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.577
2025-07-02 06:41:18.577         # do intraline marking on the synch pair
2025-07-02 06:41:18.577         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.577         if eqi is None:
2025-07-02 06:41:18.577             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.577             atags = btags = ""
2025-07-02 06:41:18.577             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.577             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.577                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.577                 if tag == 'replace':
2025-07-02 06:41:18.578                     atags += '^' * la
2025-07-02 06:41:18.578                     btags += '^' * lb
2025-07-02 06:41:18.578                 elif tag == 'delete':
2025-07-02 06:41:18.578                     atags += '-' * la
2025-07-02 06:41:18.578                 elif tag == 'insert':
2025-07-02 06:41:18.578                     btags += '+' * lb
2025-07-02 06:41:18.578                 elif tag == 'equal':
2025-07-02 06:41:18.578                     atags += ' ' * la
2025-07-02 06:41:18.578                     btags += ' ' * lb
2025-07-02 06:41:18.578                 else:
2025-07-02 06:41:18.578                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.578             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.578         else:
2025-07-02 06:41:18.578             # the synch pair is identical
2025-07-02 06:41:18.578             yield '  ' + aelt
2025-07-02 06:41:18.578
2025-07-02 06:41:18.578         # pump out diffs from after the synch point
2025-07-02 06:41:18.578 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.578
2025-07-02 06:41:18.578 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.579 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.579
2025-07-02 06:41:18.579 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.579 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.579 alo = 424, ahi = 1101
2025-07-02 06:41:18.579 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.579 blo = 424, bhi = 1101
2025-07-02 06:41:18.579
2025-07-02 06:41:18.579     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.579         g = []
2025-07-02 06:41:18.579         if alo < ahi:
2025-07-02 06:41:18.579             if blo < bhi:
2025-07-02 06:41:18.579                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.579             else:
2025-07-02 06:41:18.579                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.579         elif blo < bhi:
2025-07-02 06:41:18.579             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.579
2025-07-02 06:41:18.579 >       yield from g
2025-07-02 06:41:18.580
2025-07-02 06:41:18.580 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.580 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.580
2025-07-02 06:41:18.580 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.580 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.580 alo = 424, ahi = 1101
2025-07-02 06:41:18.580 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.580 blo = 424, bhi = 1101
2025-07-02 06:41:18.580
2025-07-02 06:41:18.580     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.580         r"""
2025-07-02 06:41:18.580         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.580         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.580         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.580         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.580
2025-07-02 06:41:18.580         Example:
2025-07-02 06:41:18.581
2025-07-02 06:41:18.581         >>> d = Differ()
2025-07-02 06:41:18.581         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.581         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.581         >>> print(''.join(results), end="")
2025-07-02 06:41:18.581         - abcDefghiJkl
2025-07-02 06:41:18.581         + abcdefGhijkl
2025-07-02 06:41:18.581         """
2025-07-02 06:41:18.581
2025-07-02 06:41:18.581         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.581         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.581         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.581         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.581         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.581
2025-07-02 06:41:18.581         # search for the pair that matches best without being identical
2025-07-02 06:41:18.581         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.581         # on junk -- unless we have to)
2025-07-02 06:41:18.582         for j in range(blo, bhi):
2025-07-02 06:41:18.582             bj = b[j]
2025-07-02 06:41:18.582             cruncher.set_seq2(bj)
2025-07-02 06:41:18.582             for i in range(alo, ahi):
2025-07-02 06:41:18.582                 ai = a[i]
2025-07-02 06:41:18.582                 if ai == bj:
2025-07-02 06:41:18.582                     if eqi is None:
2025-07-02 06:41:18.582                         eqi, eqj = i, j
2025-07-02 06:41:18.582                     continue
2025-07-02 06:41:18.582                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.582                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.582                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.582                 # compares by a factor of 3.
2025-07-02 06:41:18.582                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.582                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.582                 # of the computation is cached by cruncher
2025-07-02 06:41:18.582                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.582                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.582                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.583                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.583         if best_ratio < cutoff:
2025-07-02 06:41:18.583             # no non-identical "pretty close" pair
2025-07-02 06:41:18.583             if eqi is None:
2025-07-02 06:41:18.583                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.583                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.583                 return
2025-07-02 06:41:18.583             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.583             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.583         else:
2025-07-02 06:41:18.583             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.583             eqi = None
2025-07-02 06:41:18.583
2025-07-02 06:41:18.583         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.583         # identical
2025-07-02 06:41:18.583
2025-07-02 06:41:18.583         # pump out diffs from before the synch point
2025-07-02 06:41:18.583         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.583
2025-07-02 06:41:18.584         # do intraline marking on the synch pair
2025-07-02 06:41:18.584         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.584         if eqi is None:
2025-07-02 06:41:18.584             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.584             atags = btags = ""
2025-07-02 06:41:18.584             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.584             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.584                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.584                 if tag == 'replace':
2025-07-02 06:41:18.584                     atags += '^' * la
2025-07-02 06:41:18.584                     btags += '^' * lb
2025-07-02 06:41:18.584                 elif tag == 'delete':
2025-07-02 06:41:18.584                     atags += '-' * la
2025-07-02 06:41:18.584                 elif tag == 'insert':
2025-07-02 06:41:18.584                     btags += '+' * lb
2025-07-02 06:41:18.584                 elif tag == 'equal':
2025-07-02 06:41:18.584                     atags += ' ' * la
2025-07-02 06:41:18.584                     btags += ' ' * lb
2025-07-02 06:41:18.584                 else:
2025-07-02 06:41:18.584                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.585             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.585         else:
2025-07-02 06:41:18.585             # the synch pair is identical
2025-07-02 06:41:18.585             yield '  ' + aelt
2025-07-02 06:41:18.585
2025-07-02 06:41:18.585         # pump out diffs from after the synch point
2025-07-02 06:41:18.585 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.585
2025-07-02 06:41:18.585 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.585 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.585
2025-07-02 06:41:18.585 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.585 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.585 alo = 425, ahi = 1101
2025-07-02 06:41:18.585 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.585 blo = 425, bhi = 1101
2025-07-02 06:41:18.585
2025-07-02 06:41:18.585     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.585         g = []
2025-07-02 06:41:18.586         if alo < ahi:
2025-07-02 06:41:18.586             if blo < bhi:
2025-07-02 06:41:18.586                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.586             else:
2025-07-02 06:41:18.586                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.586         elif blo < bhi:
2025-07-02 06:41:18.586             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.586
2025-07-02 06:41:18.586 >       yield from g
2025-07-02 06:41:18.586
2025-07-02 06:41:18.586 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.586 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.586
2025-07-02 06:41:18.586 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.586 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.586 alo = 425, ahi = 1101
2025-07-02 06:41:18.586 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.586 blo = 425, bhi = 1101
2025-07-02 06:41:18.586
2025-07-02 06:41:18.587     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.587         r"""
2025-07-02 06:41:18.587         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.587         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.587         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.587         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.587
2025-07-02 06:41:18.587         Example:
2025-07-02 06:41:18.587
2025-07-02 06:41:18.587         >>> d = Differ()
2025-07-02 06:41:18.587         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.587         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.587         >>> print(''.join(results), end="")
2025-07-02 06:41:18.587         - abcDefghiJkl
2025-07-02 06:41:18.587         + abcdefGhijkl
2025-07-02 06:41:18.587         """
2025-07-02 06:41:18.587
2025-07-02 06:41:18.587         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.588         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.588         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.588         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.588         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.588
2025-07-02 06:41:18.588         # search for the pair that matches best without being identical
2025-07-02 06:41:18.588         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.588         # on junk -- unless we have to)
2025-07-02 06:41:18.588         for j in range(blo, bhi):
2025-07-02 06:41:18.588             bj = b[j]
2025-07-02 06:41:18.588             cruncher.set_seq2(bj)
2025-07-02 06:41:18.588             for i in range(alo, ahi):
2025-07-02 06:41:18.588                 ai = a[i]
2025-07-02 06:41:18.588                 if ai == bj:
2025-07-02 06:41:18.588                     if eqi is None:
2025-07-02 06:41:18.588                         eqi, eqj = i, j
2025-07-02 06:41:18.588                     continue
2025-07-02 06:41:18.588                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.588                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.588                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.589                 # compares by a factor of 3.
2025-07-02 06:41:18.589                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.589                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.589                 # of the computation is cached by cruncher
2025-07-02 06:41:18.589                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.589                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.589                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.589                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.589         if best_ratio < cutoff:
2025-07-02 06:41:18.589             # no non-identical "pretty close" pair
2025-07-02 06:41:18.589             if eqi is None:
2025-07-02 06:41:18.589                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.589                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.589                 return
2025-07-02 06:41:18.589             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.589             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.589         else:
2025-07-02 06:41:18.589             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.590             eqi = None
2025-07-02 06:41:18.590
2025-07-02 06:41:18.590         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.590         # identical
2025-07-02 06:41:18.590
2025-07-02 06:41:18.590         # pump out diffs from before the synch point
2025-07-02 06:41:18.590         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.590
2025-07-02 06:41:18.590         # do intraline marking on the synch pair
2025-07-02 06:41:18.590         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.590         if eqi is None:
2025-07-02 06:41:18.590             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.590             atags = btags = ""
2025-07-02 06:41:18.590             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.590             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.590                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.590                 if tag == 'replace':
2025-07-02 06:41:18.590                     atags += '^' * la
2025-07-02 06:41:18.590                     btags += '^' * lb
2025-07-02 06:41:18.591                 elif tag == 'delete':
2025-07-02 06:41:18.591                     atags += '-' * la
2025-07-02 06:41:18.591                 elif tag == 'insert':
2025-07-02 06:41:18.591                     btags += '+' * lb
2025-07-02 06:41:18.591                 elif tag == 'equal':
2025-07-02 06:41:18.591                     atags += ' ' * la
2025-07-02 06:41:18.591                     btags += ' ' * lb
2025-07-02 06:41:18.591                 else:
2025-07-02 06:41:18.591                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.591             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.591         else:
2025-07-02 06:41:18.591             # the synch pair is identical
2025-07-02 06:41:18.591             yield '  ' + aelt
2025-07-02 06:41:18.591
2025-07-02 06:41:18.591         # pump out diffs from after the synch point
2025-07-02 06:41:18.591 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.591
2025-07-02 06:41:18.591 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.591 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.591
2025-07-02 06:41:18.591 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.592 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.592 alo = 426, ahi = 1101
2025-07-02 06:41:18.592 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.592 blo = 426, bhi = 1101
2025-07-02 06:41:18.592
2025-07-02 06:41:18.592     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.592         g = []
2025-07-02 06:41:18.592         if alo < ahi:
2025-07-02 06:41:18.592             if blo < bhi:
2025-07-02 06:41:18.592                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.592             else:
2025-07-02 06:41:18.592                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.592         elif blo < bhi:
2025-07-02 06:41:18.592             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.592
2025-07-02 06:41:18.592 >       yield from g
2025-07-02 06:41:18.592
2025-07-02 06:41:18.592 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.592 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.592
2025-07-02 06:41:18.593 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.593 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.593 alo = 426, ahi = 1101
2025-07-02 06:41:18.593 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.593 blo = 426, bhi = 1101
2025-07-02 06:41:18.593
2025-07-02 06:41:18.593     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.593         r"""
2025-07-02 06:41:18.593         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.593         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.593         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.593         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.593
2025-07-02 06:41:18.593         Example:
2025-07-02 06:41:18.593
2025-07-02 06:41:18.593         >>> d = Differ()
2025-07-02 06:41:18.593         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.593         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.593         >>> print(''.join(results), end="")
2025-07-02 06:41:18.593         - abcDefghiJkl
2025-07-02 06:41:18.594         + abcdefGhijkl
2025-07-02 06:41:18.594         """
2025-07-02 06:41:18.594
2025-07-02 06:41:18.594         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.594         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.594         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.594         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.594         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.594
2025-07-02 06:41:18.594         # search for the pair that matches best without being identical
2025-07-02 06:41:18.594         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.594         # on junk -- unless we have to)
2025-07-02 06:41:18.594         for j in range(blo, bhi):
2025-07-02 06:41:18.594             bj = b[j]
2025-07-02 06:41:18.594             cruncher.set_seq2(bj)
2025-07-02 06:41:18.594             for i in range(alo, ahi):
2025-07-02 06:41:18.594                 ai = a[i]
2025-07-02 06:41:18.594                 if ai == bj:
2025-07-02 06:41:18.595                     if eqi is None:
2025-07-02 06:41:18.595                         eqi, eqj = i, j
2025-07-02 06:41:18.595                     continue
2025-07-02 06:41:18.595                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.595                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.595                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.595                 # compares by a factor of 3.
2025-07-02 06:41:18.595                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.595                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.595                 # of the computation is cached by cruncher
2025-07-02 06:41:18.595                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.595                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.595                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.595                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.595         if best_ratio < cutoff:
2025-07-02 06:41:18.595             # no non-identical "pretty close" pair
2025-07-02 06:41:18.595             if eqi is None:
2025-07-02 06:41:18.595                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.595                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.596                 return
2025-07-02 06:41:18.596             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.596             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.596         else:
2025-07-02 06:41:18.596             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.596             eqi = None
2025-07-02 06:41:18.596
2025-07-02 06:41:18.596         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.596         # identical
2025-07-02 06:41:18.596
2025-07-02 06:41:18.596         # pump out diffs from before the synch point
2025-07-02 06:41:18.596         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.596
2025-07-02 06:41:18.596         # do intraline marking on the synch pair
2025-07-02 06:41:18.596         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.596         if eqi is None:
2025-07-02 06:41:18.596             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.596             atags = btags = ""
2025-07-02 06:41:18.596             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.596             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.597                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.597                 if tag == 'replace':
2025-07-02 06:41:18.597                     atags += '^' * la
2025-07-02 06:41:18.597                     btags += '^' * lb
2025-07-02 06:41:18.597                 elif tag == 'delete':
2025-07-02 06:41:18.597                     atags += '-' * la
2025-07-02 06:41:18.597                 elif tag == 'insert':
2025-07-02 06:41:18.597                     btags += '+' * lb
2025-07-02 06:41:18.597                 elif tag == 'equal':
2025-07-02 06:41:18.597                     atags += ' ' * la
2025-07-02 06:41:18.597                     btags += ' ' * lb
2025-07-02 06:41:18.597                 else:
2025-07-02 06:41:18.597                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.597             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.597         else:
2025-07-02 06:41:18.597             # the synch pair is identical
2025-07-02 06:41:18.597             yield '  ' + aelt
2025-07-02 06:41:18.597
2025-07-02 06:41:18.597         # pump out diffs from after the synch point
2025-07-02 06:41:18.598 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.598
2025-07-02 06:41:18.598 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.598 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.598
2025-07-02 06:41:18.598 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.598 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.598 alo = 427, ahi = 1101
2025-07-02 06:41:18.598 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.598 blo = 427, bhi = 1101
2025-07-02 06:41:18.598
2025-07-02 06:41:18.598     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.598         g = []
2025-07-02 06:41:18.598         if alo < ahi:
2025-07-02 06:41:18.598             if blo < bhi:
2025-07-02 06:41:18.598                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.598             else:
2025-07-02 06:41:18.598                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.598         elif blo < bhi:
2025-07-02 06:41:18.599             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.599
2025-07-02 06:41:18.599 >       yield from g
2025-07-02 06:41:18.599
2025-07-02 06:41:18.599 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.599 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.599
2025-07-02 06:41:18.599 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.599 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.599 alo = 427, ahi = 1101
2025-07-02 06:41:18.599 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.599 blo = 427, bhi = 1101
2025-07-02 06:41:18.599
2025-07-02 06:41:18.599     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.599         r"""
2025-07-02 06:41:18.599         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.599         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.599         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.599         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.600
2025-07-02 06:41:18.600         Example:
2025-07-02 06:41:18.600
2025-07-02 06:41:18.600         >>> d = Differ()
2025-07-02 06:41:18.600         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.600         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.600         >>> print(''.join(results), end="")
2025-07-02 06:41:18.600         - abcDefghiJkl
2025-07-02 06:41:18.600         + abcdefGhijkl
2025-07-02 06:41:18.600         """
2025-07-02 06:41:18.600
2025-07-02 06:41:18.600         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.600         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.600         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.600         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.600         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.600
2025-07-02 06:41:18.600         # search for the pair that matches best without being identical
2025-07-02 06:41:18.601         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.601         # on junk -- unless we have to)
2025-07-02 06:41:18.601         for j in range(blo, bhi):
2025-07-02 06:41:18.601             bj = b[j]
2025-07-02 06:41:18.601             cruncher.set_seq2(bj)
2025-07-02 06:41:18.601             for i in range(alo, ahi):
2025-07-02 06:41:18.601                 ai = a[i]
2025-07-02 06:41:18.601                 if ai == bj:
2025-07-02 06:41:18.601                     if eqi is None:
2025-07-02 06:41:18.601                         eqi, eqj = i, j
2025-07-02 06:41:18.601                     continue
2025-07-02 06:41:18.601                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.601                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.601                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.601                 # compares by a factor of 3.
2025-07-02 06:41:18.601                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.601                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.601                 # of the computation is cached by cruncher
2025-07-02 06:41:18.601                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.602                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.602                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.602                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.602         if best_ratio < cutoff:
2025-07-02 06:41:18.602             # no non-identical "pretty close" pair
2025-07-02 06:41:18.602             if eqi is None:
2025-07-02 06:41:18.602                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.602                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.602                 return
2025-07-02 06:41:18.602             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.602             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.602         else:
2025-07-02 06:41:18.602             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.602             eqi = None
2025-07-02 06:41:18.602
2025-07-02 06:41:18.602         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.602         # identical
2025-07-02 06:41:18.602
2025-07-02 06:41:18.602         # pump out diffs from before the synch point
2025-07-02 06:41:18.602         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.603
2025-07-02 06:41:18.603         # do intraline marking on the synch pair
2025-07-02 06:41:18.603         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.603         if eqi is None:
2025-07-02 06:41:18.603             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.603             atags = btags = ""
2025-07-02 06:41:18.603             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.603             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.603                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.603                 if tag == 'replace':
2025-07-02 06:41:18.603                     atags += '^' * la
2025-07-02 06:41:18.603                     btags += '^' * lb
2025-07-02 06:41:18.603                 elif tag == 'delete':
2025-07-02 06:41:18.603                     atags += '-' * la
2025-07-02 06:41:18.603                 elif tag == 'insert':
2025-07-02 06:41:18.603                     btags += '+' * lb
2025-07-02 06:41:18.603                 elif tag == 'equal':
2025-07-02 06:41:18.603                     atags += ' ' * la
2025-07-02 06:41:18.603                     btags += ' ' * lb
2025-07-02 06:41:18.604                 else:
2025-07-02 06:41:18.604                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.604             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.604         else:
2025-07-02 06:41:18.604             # the synch pair is identical
2025-07-02 06:41:18.604             yield '  ' + aelt
2025-07-02 06:41:18.604
2025-07-02 06:41:18.604         # pump out diffs from after the synch point
2025-07-02 06:41:18.604 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.604
2025-07-02 06:41:18.604 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.604 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.604
2025-07-02 06:41:18.604 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.604 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.604 alo = 428, ahi = 1101
2025-07-02 06:41:18.604 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.604 blo = 428, bhi = 1101
2025-07-02 06:41:18.604
2025-07-02 06:41:18.605     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.605         g = []
2025-07-02 06:41:18.605         if alo < ahi:
2025-07-02 06:41:18.605             if blo < bhi:
2025-07-02 06:41:18.605                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.605             else:
2025-07-02 06:41:18.605                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.605         elif blo < bhi:
2025-07-02 06:41:18.605             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.605
2025-07-02 06:41:18.605 >       yield from g
2025-07-02 06:41:18.605
2025-07-02 06:41:18.605 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.605 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.605
2025-07-02 06:41:18.605 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.605 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.605 alo = 428, ahi = 1101
2025-07-02 06:41:18.605 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.605 blo = 428, bhi = 1101
2025-07-02 06:41:18.606
2025-07-02 06:41:18.606     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.606         r"""
2025-07-02 06:41:18.606         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.606         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.606         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.606         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.606
2025-07-02 06:41:18.606         Example:
2025-07-02 06:41:18.606
2025-07-02 06:41:18.606         >>> d = Differ()
2025-07-02 06:41:18.606         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.606         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.606         >>> print(''.join(results), end="")
2025-07-02 06:41:18.606         - abcDefghiJkl
2025-07-02 06:41:18.606         + abcdefGhijkl
2025-07-02 06:41:18.606         """
2025-07-02 06:41:18.607
2025-07-02 06:41:18.607         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.607         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.607         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.607         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.607         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.607
2025-07-02 06:41:18.607         # search for the pair that matches best without being identical
2025-07-02 06:41:18.607         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.607         # on junk -- unless we have to)
2025-07-02 06:41:18.607         for j in range(blo, bhi):
2025-07-02 06:41:18.607             bj = b[j]
2025-07-02 06:41:18.607             cruncher.set_seq2(bj)
2025-07-02 06:41:18.607             for i in range(alo, ahi):
2025-07-02 06:41:18.607                 ai = a[i]
2025-07-02 06:41:18.607                 if ai == bj:
2025-07-02 06:41:18.607                     if eqi is None:
2025-07-02 06:41:18.607                         eqi, eqj = i, j
2025-07-02 06:41:18.607                     continue
2025-07-02 06:41:18.607                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.608                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.608                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.608                 # compares by a factor of 3.
2025-07-02 06:41:18.608                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.608                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.608                 # of the computation is cached by cruncher
2025-07-02 06:41:18.608                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.608                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.608                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.608                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.608         if best_ratio < cutoff:
2025-07-02 06:41:18.608             # no non-identical "pretty close" pair
2025-07-02 06:41:18.608             if eqi is None:
2025-07-02 06:41:18.608                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.608                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.608                 return
2025-07-02 06:41:18.608             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.608             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.608         else:
2025-07-02 06:41:18.609             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.609             eqi = None
2025-07-02 06:41:18.609
2025-07-02 06:41:18.609         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.609         # identical
2025-07-02 06:41:18.609
2025-07-02 06:41:18.609         # pump out diffs from before the synch point
2025-07-02 06:41:18.609         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.609
2025-07-02 06:41:18.609         # do intraline marking on the synch pair
2025-07-02 06:41:18.609         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.609         if eqi is None:
2025-07-02 06:41:18.609             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.609             atags = btags = ""
2025-07-02 06:41:18.609             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.609             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.609                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.609                 if tag == 'replace':
2025-07-02 06:41:18.609                     atags += '^' * la
2025-07-02 06:41:18.610                     btags += '^' * lb
2025-07-02 06:41:18.610                 elif tag == 'delete':
2025-07-02 06:41:18.610                     atags += '-' * la
2025-07-02 06:41:18.610                 elif tag == 'insert':
2025-07-02 06:41:18.610                     btags += '+' * lb
2025-07-02 06:41:18.610                 elif tag == 'equal':
2025-07-02 06:41:18.610                     atags += ' ' * la
2025-07-02 06:41:18.610                     btags += ' ' * lb
2025-07-02 06:41:18.610                 else:
2025-07-02 06:41:18.610                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.610             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.610         else:
2025-07-02 06:41:18.610             # the synch pair is identical
2025-07-02 06:41:18.610             yield '  ' + aelt
2025-07-02 06:41:18.610
2025-07-02 06:41:18.610         # pump out diffs from after the synch point
2025-07-02 06:41:18.610 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.610
2025-07-02 06:41:18.610 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.610 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.611
2025-07-02 06:41:18.611 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.611 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.611 alo = 429, ahi = 1101
2025-07-02 06:41:18.611 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.611 blo = 429, bhi = 1101
2025-07-02 06:41:18.611
2025-07-02 06:41:18.611     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.611         g = []
2025-07-02 06:41:18.611         if alo < ahi:
2025-07-02 06:41:18.611             if blo < bhi:
2025-07-02 06:41:18.611                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.611             else:
2025-07-02 06:41:18.611                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.611         elif blo < bhi:
2025-07-02 06:41:18.611             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.611
2025-07-02 06:41:18.611 >       yield from g
2025-07-02 06:41:18.611
2025-07-02 06:41:18.612 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.612 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.612
2025-07-02 06:41:18.612 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.612 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.612 alo = 429, ahi = 1101
2025-07-02 06:41:18.612 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.612 blo = 429, bhi = 1101
2025-07-02 06:41:18.612
2025-07-02 06:41:18.612     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.612         r"""
2025-07-02 06:41:18.612         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.612         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.612         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.612         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.612
2025-07-02 06:41:18.612         Example:
2025-07-02 06:41:18.612
2025-07-02 06:41:18.612         >>> d = Differ()
2025-07-02 06:41:18.613         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.613         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.613         >>> print(''.join(results), end="")
2025-07-02 06:41:18.613         - abcDefghiJkl
2025-07-02 06:41:18.613         + abcdefGhijkl
2025-07-02 06:41:18.613         """
2025-07-02 06:41:18.613
2025-07-02 06:41:18.613         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.613         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.613         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.613         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.613         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.613
2025-07-02 06:41:18.613         # search for the pair that matches best without being identical
2025-07-02 06:41:18.613         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.613         # on junk -- unless we have to)
2025-07-02 06:41:18.613         for j in range(blo, bhi):
2025-07-02 06:41:18.613             bj = b[j]
2025-07-02 06:41:18.614             cruncher.set_seq2(bj)
2025-07-02 06:41:18.614             for i in range(alo, ahi):
2025-07-02 06:41:18.614                 ai = a[i]
2025-07-02 06:41:18.614                 if ai == bj:
2025-07-02 06:41:18.614                     if eqi is None:
2025-07-02 06:41:18.614                         eqi, eqj = i, j
2025-07-02 06:41:18.614                     continue
2025-07-02 06:41:18.614                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.614                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.614                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.614                 # compares by a factor of 3.
2025-07-02 06:41:18.614                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.614                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.614                 # of the computation is cached by cruncher
2025-07-02 06:41:18.614                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.614                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.614                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.614                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.614         if best_ratio < cutoff:
2025-07-02 06:41:18.614             # no non-identical "pretty close" pair
2025-07-02 06:41:18.615             if eqi is None:
2025-07-02 06:41:18.615                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.615                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.615                 return
2025-07-02 06:41:18.615             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.615             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.615         else:
2025-07-02 06:41:18.615             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.615             eqi = None
2025-07-02 06:41:18.615
2025-07-02 06:41:18.615         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.615         # identical
2025-07-02 06:41:18.615
2025-07-02 06:41:18.615         # pump out diffs from before the synch point
2025-07-02 06:41:18.615         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.615
2025-07-02 06:41:18.615         # do intraline marking on the synch pair
2025-07-02 06:41:18.615         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.615         if eqi is None:
2025-07-02 06:41:18.616             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.616             atags = btags = ""
2025-07-02 06:41:18.616             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.616             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.616                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.616                 if tag == 'replace':
2025-07-02 06:41:18.616                     atags += '^' * la
2025-07-02 06:41:18.616                     btags += '^' * lb
2025-07-02 06:41:18.616                 elif tag == 'delete':
2025-07-02 06:41:18.616                     atags += '-' * la
2025-07-02 06:41:18.616                 elif tag == 'insert':
2025-07-02 06:41:18.616                     btags += '+' * lb
2025-07-02 06:41:18.616                 elif tag == 'equal':
2025-07-02 06:41:18.616                     atags += ' ' * la
2025-07-02 06:41:18.616                     btags += ' ' * lb
2025-07-02 06:41:18.616                 else:
2025-07-02 06:41:18.616                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.616             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.616         else:
2025-07-02 06:41:18.616             # the synch pair is identical
2025-07-02 06:41:18.616             yield '  ' + aelt
2025-07-02 06:41:18.617
2025-07-02 06:41:18.617         # pump out diffs from after the synch point
2025-07-02 06:41:18.617 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.617
2025-07-02 06:41:18.617 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.617 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.617
2025-07-02 06:41:18.617 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.617 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.617 alo = 430, ahi = 1101
2025-07-02 06:41:18.617 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.617 blo = 430, bhi = 1101
2025-07-02 06:41:18.617
2025-07-02 06:41:18.617     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.617         g = []
2025-07-02 06:41:18.617         if alo < ahi:
2025-07-02 06:41:18.617             if blo < bhi:
2025-07-02 06:41:18.617                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.617             else:
2025-07-02 06:41:18.618                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.618         elif blo < bhi:
2025-07-02 06:41:18.618             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.618
2025-07-02 06:41:18.618 >       yield from g
2025-07-02 06:41:18.618
2025-07-02 06:41:18.618 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.618 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.618
2025-07-02 06:41:18.618 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.618 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.618 alo = 430, ahi = 1101
2025-07-02 06:41:18.618 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.618 blo = 430, bhi = 1101
2025-07-02 06:41:18.618
2025-07-02 06:41:18.618     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.618         r"""
2025-07-02 06:41:18.618         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.618         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.618         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.619         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.619
2025-07-02 06:41:18.619         Example:
2025-07-02 06:41:18.619
2025-07-02 06:41:18.619         >>> d = Differ()
2025-07-02 06:41:18.619         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.619         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.619         >>> print(''.join(results), end="")
2025-07-02 06:41:18.619         - abcDefghiJkl
2025-07-02 06:41:18.619         + abcdefGhijkl
2025-07-02 06:41:18.619         """
2025-07-02 06:41:18.619
2025-07-02 06:41:18.619         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.619         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.619         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.619         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.619         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.619
2025-07-02 06:41:18.619         # search for the pair that matches best without being identical
2025-07-02 06:41:18.620         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.620         # on junk -- unless we have to)
2025-07-02 06:41:18.620         for j in range(blo, bhi):
2025-07-02 06:41:18.620             bj = b[j]
2025-07-02 06:41:18.620             cruncher.set_seq2(bj)
2025-07-02 06:41:18.620             for i in range(alo, ahi):
2025-07-02 06:41:18.620                 ai = a[i]
2025-07-02 06:41:18.620                 if ai == bj:
2025-07-02 06:41:18.620                     if eqi is None:
2025-07-02 06:41:18.620                         eqi, eqj = i, j
2025-07-02 06:41:18.620                     continue
2025-07-02 06:41:18.620                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.620                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.620                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.620                 # compares by a factor of 3.
2025-07-02 06:41:18.620                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.620                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.620                 # of the computation is cached by cruncher
2025-07-02 06:41:18.620                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.620                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.621                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.621                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.621         if best_ratio < cutoff:
2025-07-02 06:41:18.621             # no non-identical "pretty close" pair
2025-07-02 06:41:18.621             if eqi is None:
2025-07-02 06:41:18.621                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.621                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.621                 return
2025-07-02 06:41:18.621             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.621             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.621         else:
2025-07-02 06:41:18.621             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.621             eqi = None
2025-07-02 06:41:18.621
2025-07-02 06:41:18.621         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.621         # identical
2025-07-02 06:41:18.621
2025-07-02 06:41:18.621         # pump out diffs from before the synch point
2025-07-02 06:41:18.621         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.621
2025-07-02 06:41:18.621         # do intraline marking on the synch pair
2025-07-02 06:41:18.622         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.622         if eqi is None:
2025-07-02 06:41:18.622             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.622             atags = btags = ""
2025-07-02 06:41:18.622             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.622             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.622                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.622                 if tag == 'replace':
2025-07-02 06:41:18.622                     atags += '^' * la
2025-07-02 06:41:18.622                     btags += '^' * lb
2025-07-02 06:41:18.622                 elif tag == 'delete':
2025-07-02 06:41:18.622                     atags += '-' * la
2025-07-02 06:41:18.622                 elif tag == 'insert':
2025-07-02 06:41:18.622                     btags += '+' * lb
2025-07-02 06:41:18.622                 elif tag == 'equal':
2025-07-02 06:41:18.622                     atags += ' ' * la
2025-07-02 06:41:18.622                     btags += ' ' * lb
2025-07-02 06:41:18.622                 else:
2025-07-02 06:41:18.622                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.622             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.623         else:
2025-07-02 06:41:18.623             # the synch pair is identical
2025-07-02 06:41:18.623             yield '  ' + aelt
2025-07-02 06:41:18.623
2025-07-02 06:41:18.623         # pump out diffs from after the synch point
2025-07-02 06:41:18.623 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.623
2025-07-02 06:41:18.623 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.623 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.623
2025-07-02 06:41:18.623 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.623 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.623 alo = 431, ahi = 1101
2025-07-02 06:41:18.623 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.623 blo = 431, bhi = 1101
2025-07-02 06:41:18.623
2025-07-02 06:41:18.623     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.623         g = []
2025-07-02 06:41:18.623         if alo < ahi:
2025-07-02 06:41:18.623             if blo < bhi:
2025-07-02 06:41:18.624                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.624             else:
2025-07-02 06:41:18.624                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.624         elif blo < bhi:
2025-07-02 06:41:18.624             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.624
2025-07-02 06:41:18.624 >       yield from g
2025-07-02 06:41:18.624
2025-07-02 06:41:18.624 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.624 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.624
2025-07-02 06:41:18.624 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.624 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.624 alo = 431, ahi = 1101
2025-07-02 06:41:18.624 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.624 blo = 431, bhi = 1101
2025-07-02 06:41:18.624
2025-07-02 06:41:18.625     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.625         r"""
2025-07-02 06:41:18.625         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.625         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.625         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.625         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.625
2025-07-02 06:41:18.625         Example:
2025-07-02 06:41:18.625
2025-07-02 06:41:18.625         >>> d = Differ()
2025-07-02 06:41:18.625         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.625         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.625         >>> print(''.join(results), end="")
2025-07-02 06:41:18.625         - abcDefghiJkl
2025-07-02 06:41:18.625         + abcdefGhijkl
2025-07-02 06:41:18.625         """
2025-07-02 06:41:18.625
2025-07-02 06:41:18.625         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.626         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.626         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.626         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.626         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.626
2025-07-02 06:41:18.626         # search for the pair that matches best without being identical
2025-07-02 06:41:18.626         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.626         # on junk -- unless we have to)
2025-07-02 06:41:18.626         for j in range(blo, bhi):
2025-07-02 06:41:18.626             bj = b[j]
2025-07-02 06:41:18.626             cruncher.set_seq2(bj)
2025-07-02 06:41:18.626             for i in range(alo, ahi):
2025-07-02 06:41:18.626                 ai = a[i]
2025-07-02 06:41:18.626                 if ai == bj:
2025-07-02 06:41:18.626                     if eqi is None:
2025-07-02 06:41:18.626                         eqi, eqj = i, j
2025-07-02 06:41:18.626                     continue
2025-07-02 06:41:18.626                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.626                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.626                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.627                 # compares by a factor of 3.
2025-07-02 06:41:18.627                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.627                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.627                 # of the computation is cached by cruncher
2025-07-02 06:41:18.627                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.627                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.627                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.627                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.627         if best_ratio < cutoff:
2025-07-02 06:41:18.627             # no non-identical "pretty close" pair
2025-07-02 06:41:18.627             if eqi is None:
2025-07-02 06:41:18.627                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.627                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.627                 return
2025-07-02 06:41:18.627             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.627             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.627         else:
2025-07-02 06:41:18.627             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.628             eqi = None
2025-07-02 06:41:18.628
2025-07-02 06:41:18.628         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.628         # identical
2025-07-02 06:41:18.628
2025-07-02 06:41:18.628         # pump out diffs from before the synch point
2025-07-02 06:41:18.628         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.628
2025-07-02 06:41:18.628         # do intraline marking on the synch pair
2025-07-02 06:41:18.628         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.628         if eqi is None:
2025-07-02 06:41:18.628             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.628             atags = btags = ""
2025-07-02 06:41:18.628             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.628             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.628                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.628                 if tag == 'replace':
2025-07-02 06:41:18.628                     atags += '^' * la
2025-07-02 06:41:18.628                     btags += '^' * lb
2025-07-02 06:41:18.628                 elif tag == 'delete':
2025-07-02 06:41:18.629                     atags += '-' * la
2025-07-02 06:41:18.629                 elif tag == 'insert':
2025-07-02 06:41:18.629                     btags += '+' * lb
2025-07-02 06:41:18.629                 elif tag == 'equal':
2025-07-02 06:41:18.629                     atags += ' ' * la
2025-07-02 06:41:18.629                     btags += ' ' * lb
2025-07-02 06:41:18.629                 else:
2025-07-02 06:41:18.629                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.629             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.629         else:
2025-07-02 06:41:18.629             # the synch pair is identical
2025-07-02 06:41:18.629             yield '  ' + aelt
2025-07-02 06:41:18.629
2025-07-02 06:41:18.629         # pump out diffs from after the synch point
2025-07-02 06:41:18.629 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.629
2025-07-02 06:41:18.629 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.629 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.629
2025-07-02 06:41:18.629 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.630 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.630 alo = 432, ahi = 1101
2025-07-02 06:41:18.630 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.630 blo = 432, bhi = 1101
2025-07-02 06:41:18.630
2025-07-02 06:41:18.630     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.630         g = []
2025-07-02 06:41:18.630         if alo < ahi:
2025-07-02 06:41:18.630             if blo < bhi:
2025-07-02 06:41:18.630                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.630             else:
2025-07-02 06:41:18.630                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.630         elif blo < bhi:
2025-07-02 06:41:18.630             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.630
2025-07-02 06:41:18.630 >       yield from g
2025-07-02 06:41:18.630
2025-07-02 06:41:18.630 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.630 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.630
2025-07-02 06:41:18.631 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.631 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.631 alo = 432, ahi = 1101
2025-07-02 06:41:18.631 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.631 blo = 432, bhi = 1101
2025-07-02 06:41:18.631
2025-07-02 06:41:18.631     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.631         r"""
2025-07-02 06:41:18.631         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.631         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.631         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.631         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.631
2025-07-02 06:41:18.631         Example:
2025-07-02 06:41:18.631
2025-07-02 06:41:18.631         >>> d = Differ()
2025-07-02 06:41:18.631         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.631         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.631         >>> print(''.join(results), end="")
2025-07-02 06:41:18.631         - abcDefghiJkl
2025-07-02 06:41:18.632         + abcdefGhijkl
2025-07-02 06:41:18.632         """
2025-07-02 06:41:18.632
2025-07-02 06:41:18.632         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.632         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.632         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.632         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.632         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.632
2025-07-02 06:41:18.632         # search for the pair that matches best without being identical
2025-07-02 06:41:18.632         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.632         # on junk -- unless we have to)
2025-07-02 06:41:18.632         for j in range(blo, bhi):
2025-07-02 06:41:18.632             bj = b[j]
2025-07-02 06:41:18.632             cruncher.set_seq2(bj)
2025-07-02 06:41:18.632             for i in range(alo, ahi):
2025-07-02 06:41:18.632                 ai = a[i]
2025-07-02 06:41:18.633                 if ai == bj:
2025-07-02 06:41:18.633                     if eqi is None:
2025-07-02 06:41:18.633                         eqi, eqj = i, j
2025-07-02 06:41:18.633                     continue
2025-07-02 06:41:18.633                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.633                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.633                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.633                 # compares by a factor of 3.
2025-07-02 06:41:18.633                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.633                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.633                 # of the computation is cached by cruncher
2025-07-02 06:41:18.633                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.633                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.633                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.633                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.633         if best_ratio < cutoff:
2025-07-02 06:41:18.633             # no non-identical "pretty close" pair
2025-07-02 06:41:18.633             if eqi is None:
2025-07-02 06:41:18.633                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.634                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.634                 return
2025-07-02 06:41:18.634             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.634             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.634         else:
2025-07-02 06:41:18.634             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.634             eqi = None
2025-07-02 06:41:18.634
2025-07-02 06:41:18.634         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.634         # identical
2025-07-02 06:41:18.634
2025-07-02 06:41:18.634         # pump out diffs from before the synch point
2025-07-02 06:41:18.634         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.634
2025-07-02 06:41:18.634         # do intraline marking on the synch pair
2025-07-02 06:41:18.634         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.634         if eqi is None:
2025-07-02 06:41:18.634             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.634             atags = btags = ""
2025-07-02 06:41:18.634             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.635             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.635                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.635                 if tag == 'replace':
2025-07-02 06:41:18.635                     atags += '^' * la
2025-07-02 06:41:18.635                     btags += '^' * lb
2025-07-02 06:41:18.635                 elif tag == 'delete':
2025-07-02 06:41:18.635                     atags += '-' * la
2025-07-02 06:41:18.635                 elif tag == 'insert':
2025-07-02 06:41:18.635                     btags += '+' * lb
2025-07-02 06:41:18.635                 elif tag == 'equal':
2025-07-02 06:41:18.635                     atags += ' ' * la
2025-07-02 06:41:18.635                     btags += ' ' * lb
2025-07-02 06:41:18.635                 else:
2025-07-02 06:41:18.635                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.635             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.635         else:
2025-07-02 06:41:18.635             # the synch pair is identical
2025-07-02 06:41:18.635             yield '  ' + aelt
2025-07-02 06:41:18.636
2025-07-02 06:41:18.636         # pump out diffs from after the synch point
2025-07-02 06:41:18.636 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.636
2025-07-02 06:41:18.636 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.636 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.636
2025-07-02 06:41:18.636 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.636 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.636 alo = 433, ahi = 1101
2025-07-02 06:41:18.636 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.636 blo = 433, bhi = 1101
2025-07-02 06:41:18.636
2025-07-02 06:41:18.636     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.636         g = []
2025-07-02 06:41:18.636         if alo < ahi:
2025-07-02 06:41:18.636             if blo < bhi:
2025-07-02 06:41:18.636                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.636             else:
2025-07-02 06:41:18.636                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.637         elif blo < bhi:
2025-07-02 06:41:18.637             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.637
2025-07-02 06:41:18.637 >       yield from g
2025-07-02 06:41:18.637
2025-07-02 06:41:18.637 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.637 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.637
2025-07-02 06:41:18.637 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.637 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.637 alo = 433, ahi = 1101
2025-07-02 06:41:18.637 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.637 blo = 433, bhi = 1101
2025-07-02 06:41:18.637
2025-07-02 06:41:18.637     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.637         r"""
2025-07-02 06:41:18.637         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.637         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.637         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.637         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.638
2025-07-02 06:41:18.638         Example:
2025-07-02 06:41:18.638
2025-07-02 06:41:18.638         >>> d = Differ()
2025-07-02 06:41:18.638         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.638         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.638         >>> print(''.join(results), end="")
2025-07-02 06:41:18.638         - abcDefghiJkl
2025-07-02 06:41:18.638         + abcdefGhijkl
2025-07-02 06:41:18.638         """
2025-07-02 06:41:18.638
2025-07-02 06:41:18.638         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.638         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.638         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.638         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.638         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.638
2025-07-02 06:41:18.638         # search for the pair that matches best without being identical
2025-07-02 06:41:18.639         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.639         # on junk -- unless we have to)
2025-07-02 06:41:18.639         for j in range(blo, bhi):
2025-07-02 06:41:18.639             bj = b[j]
2025-07-02 06:41:18.639             cruncher.set_seq2(bj)
2025-07-02 06:41:18.639             for i in range(alo, ahi):
2025-07-02 06:41:18.639                 ai = a[i]
2025-07-02 06:41:18.639                 if ai == bj:
2025-07-02 06:41:18.639                     if eqi is None:
2025-07-02 06:41:18.639                         eqi, eqj = i, j
2025-07-02 06:41:18.639                     continue
2025-07-02 06:41:18.639                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.639                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.639                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.639                 # compares by a factor of 3.
2025-07-02 06:41:18.639                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.639                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.639                 # of the computation is cached by cruncher
2025-07-02 06:41:18.639                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.639                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.639                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.640                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.640         if best_ratio < cutoff:
2025-07-02 06:41:18.640             # no non-identical "pretty close" pair
2025-07-02 06:41:18.640             if eqi is None:
2025-07-02 06:41:18.640                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.640                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.640                 return
2025-07-02 06:41:18.640             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.640             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.640         else:
2025-07-02 06:41:18.640             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.640             eqi = None
2025-07-02 06:41:18.640
2025-07-02 06:41:18.640         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.640         # identical
2025-07-02 06:41:18.640
2025-07-02 06:41:18.640         # pump out diffs from before the synch point
2025-07-02 06:41:18.640         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.640
2025-07-02 06:41:18.640         # do intraline marking on the synch pair
2025-07-02 06:41:18.641         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.641         if eqi is None:
2025-07-02 06:41:18.641             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.641             atags = btags = ""
2025-07-02 06:41:18.641             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.641             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.641                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.641                 if tag == 'replace':
2025-07-02 06:41:18.641                     atags += '^' * la
2025-07-02 06:41:18.641                     btags += '^' * lb
2025-07-02 06:41:18.641                 elif tag == 'delete':
2025-07-02 06:41:18.641                     atags += '-' * la
2025-07-02 06:41:18.641                 elif tag == 'insert':
2025-07-02 06:41:18.641                     btags += '+' * lb
2025-07-02 06:41:18.641                 elif tag == 'equal':
2025-07-02 06:41:18.641                     atags += ' ' * la
2025-07-02 06:41:18.641                     btags += ' ' * lb
2025-07-02 06:41:18.641                 else:
2025-07-02 06:41:18.641                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.641             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.642         else:
2025-07-02 06:41:18.642             # the synch pair is identical
2025-07-02 06:41:18.642             yield '  ' + aelt
2025-07-02 06:41:18.642
2025-07-02 06:41:18.642         # pump out diffs from after the synch point
2025-07-02 06:41:18.642 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.642
2025-07-02 06:41:18.642 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.642 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.642
2025-07-02 06:41:18.642 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.642 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.642 alo = 434, ahi = 1101
2025-07-02 06:41:18.642 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.642 blo = 434, bhi = 1101
2025-07-02 06:41:18.642
2025-07-02 06:41:18.642     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.643         g = []
2025-07-02 06:41:18.643         if alo < ahi:
2025-07-02 06:41:18.643             if blo < bhi:
2025-07-02 06:41:18.643                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.643             else:
2025-07-02 06:41:18.643                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.643         elif blo < bhi:
2025-07-02 06:41:18.643             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.643
2025-07-02 06:41:18.643 >       yield from g
2025-07-02 06:41:18.643
2025-07-02 06:41:18.643 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.643 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.643
2025-07-02 06:41:18.643 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.643 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.643 alo = 434, ahi = 1101
2025-07-02 06:41:18.643 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.643 blo = 434, bhi = 1101
2025-07-02 06:41:18.644
2025-07-02 06:41:18.644     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.644         r"""
2025-07-02 06:41:18.644         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.644         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.644         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.644         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.644
2025-07-02 06:41:18.644         Example:
2025-07-02 06:41:18.644
2025-07-02 06:41:18.644         >>> d = Differ()
2025-07-02 06:41:18.644         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.644         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.644         >>> print(''.join(results), end="")
2025-07-02 06:41:18.644         - abcDefghiJkl
2025-07-02 06:41:18.644         + abcdefGhijkl
2025-07-02 06:41:18.644         """
2025-07-02 06:41:18.645
2025-07-02 06:41:18.645         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.645         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.645         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.645         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.645         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.645
2025-07-02 06:41:18.645         # search for the pair that matches best without being identical
2025-07-02 06:41:18.645         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.645         # on junk -- unless we have to)
2025-07-02 06:41:18.645         for j in range(blo, bhi):
2025-07-02 06:41:18.645             bj = b[j]
2025-07-02 06:41:18.645             cruncher.set_seq2(bj)
2025-07-02 06:41:18.645             for i in range(alo, ahi):
2025-07-02 06:41:18.645                 ai = a[i]
2025-07-02 06:41:18.645                 if ai == bj:
2025-07-02 06:41:18.645                     if eqi is None:
2025-07-02 06:41:18.645                         eqi, eqj = i, j
2025-07-02 06:41:18.645                     continue
2025-07-02 06:41:18.645                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.646                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.646                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.646                 # compares by a factor of 3.
2025-07-02 06:41:18.646                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.646                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.646                 # of the computation is cached by cruncher
2025-07-02 06:41:18.646                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.646                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.646                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.646                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.646         if best_ratio < cutoff:
2025-07-02 06:41:18.646             # no non-identical "pretty close" pair
2025-07-02 06:41:18.646             if eqi is None:
2025-07-02 06:41:18.646                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.646                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.646                 return
2025-07-02 06:41:18.646             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.646             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.646         else:
2025-07-02 06:41:18.647             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.647             eqi = None
2025-07-02 06:41:18.647
2025-07-02 06:41:18.647         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.647         # identical
2025-07-02 06:41:18.647
2025-07-02 06:41:18.647         # pump out diffs from before the synch point
2025-07-02 06:41:18.647         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.647
2025-07-02 06:41:18.647         # do intraline marking on the synch pair
2025-07-02 06:41:18.647         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.647         if eqi is None:
2025-07-02 06:41:18.647             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.647             atags = btags = ""
2025-07-02 06:41:18.647             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.647             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.647                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.647                 if tag == 'replace':
2025-07-02 06:41:18.647                     atags += '^' * la
2025-07-02 06:41:18.647                     btags += '^' * lb
2025-07-02 06:41:18.648                 elif tag == 'delete':
2025-07-02 06:41:18.648                     atags += '-' * la
2025-07-02 06:41:18.648                 elif tag == 'insert':
2025-07-02 06:41:18.648                     btags += '+' * lb
2025-07-02 06:41:18.648                 elif tag == 'equal':
2025-07-02 06:41:18.648                     atags += ' ' * la
2025-07-02 06:41:18.648                     btags += ' ' * lb
2025-07-02 06:41:18.648                 else:
2025-07-02 06:41:18.648                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.648             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.648         else:
2025-07-02 06:41:18.648             # the synch pair is identical
2025-07-02 06:41:18.648             yield '  ' + aelt
2025-07-02 06:41:18.648
2025-07-02 06:41:18.648         # pump out diffs from after the synch point
2025-07-02 06:41:18.648 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.648
2025-07-02 06:41:18.648 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.648 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.648
2025-07-02 06:41:18.649 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.649 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.649 alo = 435, ahi = 1101
2025-07-02 06:41:18.649 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.649 blo = 435, bhi = 1101
2025-07-02 06:41:18.649
2025-07-02 06:41:18.649     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.649         g = []
2025-07-02 06:41:18.649         if alo < ahi:
2025-07-02 06:41:18.649             if blo < bhi:
2025-07-02 06:41:18.649                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.649             else:
2025-07-02 06:41:18.649                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.649         elif blo < bhi:
2025-07-02 06:41:18.649             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.649
2025-07-02 06:41:18.649 >       yield from g
2025-07-02 06:41:18.649
2025-07-02 06:41:18.649 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.650 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.650
2025-07-02 06:41:18.650 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.650 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.650 alo = 435, ahi = 1101
2025-07-02 06:41:18.650 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.650 blo = 435, bhi = 1101
2025-07-02 06:41:18.650
2025-07-02 06:41:18.650     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.650         r"""
2025-07-02 06:41:18.650         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.650         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.650         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.650         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.650
2025-07-02 06:41:18.650         Example:
2025-07-02 06:41:18.650
2025-07-02 06:41:18.650         >>> d = Differ()
2025-07-02 06:41:18.651         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.651         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.651         >>> print(''.join(results), end="")
2025-07-02 06:41:18.651         - abcDefghiJkl
2025-07-02 06:41:18.651         + abcdefGhijkl
2025-07-02 06:41:18.651         """
2025-07-02 06:41:18.651
2025-07-02 06:41:18.651         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.651         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.651         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.651         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.651         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.651
2025-07-02 06:41:18.651         # search for the pair that matches best without being identical
2025-07-02 06:41:18.651         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.651         # on junk -- unless we have to)
2025-07-02 06:41:18.651         for j in range(blo, bhi):
2025-07-02 06:41:18.651             bj = b[j]
2025-07-02 06:41:18.652             cruncher.set_seq2(bj)
2025-07-02 06:41:18.652             for i in range(alo, ahi):
2025-07-02 06:41:18.652                 ai = a[i]
2025-07-02 06:41:18.652                 if ai == bj:
2025-07-02 06:41:18.652                     if eqi is None:
2025-07-02 06:41:18.652                         eqi, eqj = i, j
2025-07-02 06:41:18.652                     continue
2025-07-02 06:41:18.652                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.652                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.652                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.652                 # compares by a factor of 3.
2025-07-02 06:41:18.652                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.652                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.652                 # of the computation is cached by cruncher
2025-07-02 06:41:18.652                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.652                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.652                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.652                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.652         if best_ratio < cutoff:
2025-07-02 06:41:18.652             # no non-identical "pretty close" pair
2025-07-02 06:41:18.653             if eqi is None:
2025-07-02 06:41:18.653                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.653                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.653                 return
2025-07-02 06:41:18.653             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.653             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.653         else:
2025-07-02 06:41:18.653             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.653             eqi = None
2025-07-02 06:41:18.653
2025-07-02 06:41:18.653         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.653         # identical
2025-07-02 06:41:18.653
2025-07-02 06:41:18.653         # pump out diffs from before the synch point
2025-07-02 06:41:18.653         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.653
2025-07-02 06:41:18.653         # do intraline marking on the synch pair
2025-07-02 06:41:18.653         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.653         if eqi is None:
2025-07-02 06:41:18.653             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.654             atags = btags = ""
2025-07-02 06:41:18.654             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.654             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.654                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.654                 if tag == 'replace':
2025-07-02 06:41:18.654                     atags += '^' * la
2025-07-02 06:41:18.654                     btags += '^' * lb
2025-07-02 06:41:18.654                 elif tag == 'delete':
2025-07-02 06:41:18.654                     atags += '-' * la
2025-07-02 06:41:18.654                 elif tag == 'insert':
2025-07-02 06:41:18.654                     btags += '+' * lb
2025-07-02 06:41:18.654                 elif tag == 'equal':
2025-07-02 06:41:18.654                     atags += ' ' * la
2025-07-02 06:41:18.654                     btags += ' ' * lb
2025-07-02 06:41:18.654                 else:
2025-07-02 06:41:18.654                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.654             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.654         else:
2025-07-02 06:41:18.654             # the synch pair is identical
2025-07-02 06:41:18.654             yield '  ' + aelt
2025-07-02 06:41:18.654
2025-07-02 06:41:18.655         # pump out diffs from after the synch point
2025-07-02 06:41:18.655 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.655
2025-07-02 06:41:18.655 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.655 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.655
2025-07-02 06:41:18.655 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.655 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.655 alo = 436, ahi = 1101
2025-07-02 06:41:18.655 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.655 blo = 436, bhi = 1101
2025-07-02 06:41:18.655
2025-07-02 06:41:18.655     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.655         g = []
2025-07-02 06:41:18.655         if alo < ahi:
2025-07-02 06:41:18.655             if blo < bhi:
2025-07-02 06:41:18.655                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.655             else:
2025-07-02 06:41:18.655                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.655         elif blo < bhi:
2025-07-02 06:41:18.656             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.656
2025-07-02 06:41:18.656 >       yield from g
2025-07-02 06:41:18.656
2025-07-02 06:41:18.656 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.656 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.656
2025-07-02 06:41:18.656 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.656 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.656 alo = 436, ahi = 1101
2025-07-02 06:41:18.656 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.656 blo = 436, bhi = 1101
2025-07-02 06:41:18.656
2025-07-02 06:41:18.656     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.656         r"""
2025-07-02 06:41:18.656         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.656         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.656         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.656         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.656
2025-07-02 06:41:18.657         Example:
2025-07-02 06:41:18.657
2025-07-02 06:41:18.657         >>> d = Differ()
2025-07-02 06:41:18.657         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.657         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.657         >>> print(''.join(results), end="")
2025-07-02 06:41:18.657         - abcDefghiJkl
2025-07-02 06:41:18.657         + abcdefGhijkl
2025-07-02 06:41:18.657         """
2025-07-02 06:41:18.657
2025-07-02 06:41:18.657         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.657         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.657         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.657         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.657         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.658
2025-07-02 06:41:18.658         # search for the pair that matches best without being identical
2025-07-02 06:41:18.658         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.658         # on junk -- unless we have to)
2025-07-02 06:41:18.658         for j in range(blo, bhi):
2025-07-02 06:41:18.658             bj = b[j]
2025-07-02 06:41:18.658             cruncher.set_seq2(bj)
2025-07-02 06:41:18.658             for i in range(alo, ahi):
2025-07-02 06:41:18.658                 ai = a[i]
2025-07-02 06:41:18.658                 if ai == bj:
2025-07-02 06:41:18.658                     if eqi is None:
2025-07-02 06:41:18.658                         eqi, eqj = i, j
2025-07-02 06:41:18.658                     continue
2025-07-02 06:41:18.658                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.658                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.658                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.658                 # compares by a factor of 3.
2025-07-02 06:41:18.658                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.658                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.658                 # of the computation is cached by cruncher
2025-07-02 06:41:18.659                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.659                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.659                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.659                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.659         if best_ratio < cutoff:
2025-07-02 06:41:18.659             # no non-identical "pretty close" pair
2025-07-02 06:41:18.659             if eqi is None:
2025-07-02 06:41:18.659                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.659                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.659                 return
2025-07-02 06:41:18.659             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.659             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.659         else:
2025-07-02 06:41:18.659             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.659             eqi = None
2025-07-02 06:41:18.659
2025-07-02 06:41:18.659         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.660         # identical
2025-07-02 06:41:18.660
2025-07-02 06:41:18.660         # pump out diffs from before the synch point
2025-07-02 06:41:18.660         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.660
2025-07-02 06:41:18.660         # do intraline marking on the synch pair
2025-07-02 06:41:18.660         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.660         if eqi is None:
2025-07-02 06:41:18.660             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.660             atags = btags = ""
2025-07-02 06:41:18.660             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.660             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.660                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.660                 if tag == 'replace':
2025-07-02 06:41:18.660                     atags += '^' * la
2025-07-02 06:41:18.660                     btags += '^' * lb
2025-07-02 06:41:18.660                 elif tag == 'delete':
2025-07-02 06:41:18.660                     atags += '-' * la
2025-07-02 06:41:18.660                 elif tag == 'insert':
2025-07-02 06:41:18.660                     btags += '+' * lb
2025-07-02 06:41:18.661                 elif tag == 'equal':
2025-07-02 06:41:18.661                     atags += ' ' * la
2025-07-02 06:41:18.661                     btags += ' ' * lb
2025-07-02 06:41:18.661                 else:
2025-07-02 06:41:18.661                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.661             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.661         else:
2025-07-02 06:41:18.661             # the synch pair is identical
2025-07-02 06:41:18.661             yield '  ' + aelt
2025-07-02 06:41:18.661
2025-07-02 06:41:18.661         # pump out diffs from after the synch point
2025-07-02 06:41:18.661 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.661
2025-07-02 06:41:18.661 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.661 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.661
2025-07-02 06:41:18.661 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.661 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.661 alo = 437, ahi = 1101
2025-07-02 06:41:18.661 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.662 blo = 437, bhi = 1101
2025-07-02 06:41:18.662
2025-07-02 06:41:18.662     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.662         g = []
2025-07-02 06:41:18.662         if alo < ahi:
2025-07-02 06:41:18.662             if blo < bhi:
2025-07-02 06:41:18.662                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.662             else:
2025-07-02 06:41:18.662                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.662         elif blo < bhi:
2025-07-02 06:41:18.662             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.662
2025-07-02 06:41:18.662 >       yield from g
2025-07-02 06:41:18.662
2025-07-02 06:41:18.662 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.662 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.662
2025-07-02 06:41:18.662 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.662 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.662 alo = 437, ahi = 1101
2025-07-02 06:41:18.663 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.663 blo = 437, bhi = 1101
2025-07-02 06:41:18.663
2025-07-02 06:41:18.663     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.663         r"""
2025-07-02 06:41:18.663         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.663         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.663         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.663         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.663
2025-07-02 06:41:18.663         Example:
2025-07-02 06:41:18.663
2025-07-02 06:41:18.663         >>> d = Differ()
2025-07-02 06:41:18.663         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.663         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.663         >>> print(''.join(results), end="")
2025-07-02 06:41:18.663         - abcDefghiJkl
2025-07-02 06:41:18.663         + abcdefGhijkl
2025-07-02 06:41:18.664         """
2025-07-02 06:41:18.664
2025-07-02 06:41:18.664         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.664         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.664         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.664         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.664         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.664
2025-07-02 06:41:18.664         # search for the pair that matches best without being identical
2025-07-02 06:41:18.664         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.664         # on junk -- unless we have to)
2025-07-02 06:41:18.664         for j in range(blo, bhi):
2025-07-02 06:41:18.664             bj = b[j]
2025-07-02 06:41:18.664             cruncher.set_seq2(bj)
2025-07-02 06:41:18.664             for i in range(alo, ahi):
2025-07-02 06:41:18.664                 ai = a[i]
2025-07-02 06:41:18.664                 if ai == bj:
2025-07-02 06:41:18.664                     if eqi is None:
2025-07-02 06:41:18.664                         eqi, eqj = i, j
2025-07-02 06:41:18.664                     continue
2025-07-02 06:41:18.664                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.665                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.665                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.665                 # compares by a factor of 3.
2025-07-02 06:41:18.665                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.665                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.665                 # of the computation is cached by cruncher
2025-07-02 06:41:18.665                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.665                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.665                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.665                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.665         if best_ratio < cutoff:
2025-07-02 06:41:18.665             # no non-identical "pretty close" pair
2025-07-02 06:41:18.665             if eqi is None:
2025-07-02 06:41:18.665                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.665                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.665                 return
2025-07-02 06:41:18.665             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.665             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.665         else:
2025-07-02 06:41:18.665             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.666             eqi = None
2025-07-02 06:41:18.666
2025-07-02 06:41:18.666         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.666         # identical
2025-07-02 06:41:18.666
2025-07-02 06:41:18.666         # pump out diffs from before the synch point
2025-07-02 06:41:18.666         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.666
2025-07-02 06:41:18.666         # do intraline marking on the synch pair
2025-07-02 06:41:18.666         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.666         if eqi is None:
2025-07-02 06:41:18.666             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.666             atags = btags = ""
2025-07-02 06:41:18.666             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.666             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.666                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.666                 if tag == 'replace':
2025-07-02 06:41:18.666                     atags += '^' * la
2025-07-02 06:41:18.666                     btags += '^' * lb
2025-07-02 06:41:18.666                 elif tag == 'delete':
2025-07-02 06:41:18.666                     atags += '-' * la
2025-07-02 06:41:18.667                 elif tag == 'insert':
2025-07-02 06:41:18.667                     btags += '+' * lb
2025-07-02 06:41:18.667                 elif tag == 'equal':
2025-07-02 06:41:18.667                     atags += ' ' * la
2025-07-02 06:41:18.667                     btags += ' ' * lb
2025-07-02 06:41:18.667                 else:
2025-07-02 06:41:18.667                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.667             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.667         else:
2025-07-02 06:41:18.667             # the synch pair is identical
2025-07-02 06:41:18.667             yield '  ' + aelt
2025-07-02 06:41:18.667
2025-07-02 06:41:18.667         # pump out diffs from after the synch point
2025-07-02 06:41:18.667 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.667
2025-07-02 06:41:18.667 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.667 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.667
2025-07-02 06:41:18.667 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.667 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.668 alo = 438, ahi = 1101
2025-07-02 06:41:18.668 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.668 blo = 438, bhi = 1101
2025-07-02 06:41:18.668
2025-07-02 06:41:18.668     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.668         g = []
2025-07-02 06:41:18.668         if alo < ahi:
2025-07-02 06:41:18.668             if blo < bhi:
2025-07-02 06:41:18.668                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.668             else:
2025-07-02 06:41:18.668                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.668         elif blo < bhi:
2025-07-02 06:41:18.668             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.668
2025-07-02 06:41:18.668 >       yield from g
2025-07-02 06:41:18.668
2025-07-02 06:41:18.668 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.668 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.669
2025-07-02 06:41:18.669 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.669 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.669 alo = 438, ahi = 1101
2025-07-02 06:41:18.669 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.669 blo = 438, bhi = 1101
2025-07-02 06:41:18.669
2025-07-02 06:41:18.669     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.669         r"""
2025-07-02 06:41:18.669         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.669         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.669         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.669         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.669
2025-07-02 06:41:18.669         Example:
2025-07-02 06:41:18.669
2025-07-02 06:41:18.669         >>> d = Differ()
2025-07-02 06:41:18.669         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.669         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.670         >>> print(''.join(results), end="")
2025-07-02 06:41:18.670         - abcDefghiJkl
2025-07-02 06:41:18.670         + abcdefGhijkl
2025-07-02 06:41:18.670         """
2025-07-02 06:41:18.670
2025-07-02 06:41:18.670         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.670         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.670         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.670         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.670         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.670
2025-07-02 06:41:18.670         # search for the pair that matches best without being identical
2025-07-02 06:41:18.670         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.670         # on junk -- unless we have to)
2025-07-02 06:41:18.670         for j in range(blo, bhi):
2025-07-02 06:41:18.670             bj = b[j]
2025-07-02 06:41:18.670             cruncher.set_seq2(bj)
2025-07-02 06:41:18.670             for i in range(alo, ahi):
2025-07-02 06:41:18.671                 ai = a[i]
2025-07-02 06:41:18.671                 if ai == bj:
2025-07-02 06:41:18.671                     if eqi is None:
2025-07-02 06:41:18.671                         eqi, eqj = i, j
2025-07-02 06:41:18.671                     continue
2025-07-02 06:41:18.671                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.671                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.671                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.671                 # compares by a factor of 3.
2025-07-02 06:41:18.671                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.671                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.671                 # of the computation is cached by cruncher
2025-07-02 06:41:18.671                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.671                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.671                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.671                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.671         if best_ratio < cutoff:
2025-07-02 06:41:18.671             # no non-identical "pretty close" pair
2025-07-02 06:41:18.671             if eqi is None:
2025-07-02 06:41:18.671                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.671                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.672                 return
2025-07-02 06:41:18.672             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.672             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.672         else:
2025-07-02 06:41:18.672             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.672             eqi = None
2025-07-02 06:41:18.672
2025-07-02 06:41:18.672         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.672         # identical
2025-07-02 06:41:18.672
2025-07-02 06:41:18.672         # pump out diffs from before the synch point
2025-07-02 06:41:18.672         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.672
2025-07-02 06:41:18.672         # do intraline marking on the synch pair
2025-07-02 06:41:18.672         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.672         if eqi is None:
2025-07-02 06:41:18.672             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.672             atags = btags = ""
2025-07-02 06:41:18.672             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.672             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.673                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.673                 if tag == 'replace':
2025-07-02 06:41:18.673                     atags += '^' * la
2025-07-02 06:41:18.673                     btags += '^' * lb
2025-07-02 06:41:18.673                 elif tag == 'delete':
2025-07-02 06:41:18.673                     atags += '-' * la
2025-07-02 06:41:18.673                 elif tag == 'insert':
2025-07-02 06:41:18.673                     btags += '+' * lb
2025-07-02 06:41:18.673                 elif tag == 'equal':
2025-07-02 06:41:18.673                     atags += ' ' * la
2025-07-02 06:41:18.673                     btags += ' ' * lb
2025-07-02 06:41:18.673                 else:
2025-07-02 06:41:18.673                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.673             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.673         else:
2025-07-02 06:41:18.673             # the synch pair is identical
2025-07-02 06:41:18.673             yield '  ' + aelt
2025-07-02 06:41:18.673
2025-07-02 06:41:18.674         # pump out diffs from after the synch point
2025-07-02 06:41:18.674 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.674
2025-07-02 06:41:18.674 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.674 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.674
2025-07-02 06:41:18.674 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.674 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.674 alo = 439, ahi = 1101
2025-07-02 06:41:18.674 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.674 blo = 439, bhi = 1101
2025-07-02 06:41:18.674
2025-07-02 06:41:18.674     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.674         g = []
2025-07-02 06:41:18.674         if alo < ahi:
2025-07-02 06:41:18.674             if blo < bhi:
2025-07-02 06:41:18.674                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.674             else:
2025-07-02 06:41:18.674                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.675         elif blo < bhi:
2025-07-02 06:41:18.675             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.675
2025-07-02 06:41:18.675 >       yield from g
2025-07-02 06:41:18.675
2025-07-02 06:41:18.675 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.675 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.675
2025-07-02 06:41:18.675 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.675 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.675 alo = 439, ahi = 1101
2025-07-02 06:41:18.675 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.675 blo = 439, bhi = 1101
2025-07-02 06:41:18.675
2025-07-02 06:41:18.675     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.675         r"""
2025-07-02 06:41:18.675         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.675         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.675         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.675         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.676
2025-07-02 06:41:18.676         Example:
2025-07-02 06:41:18.676
2025-07-02 06:41:18.676         >>> d = Differ()
2025-07-02 06:41:18.676         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.676         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.676         >>> print(''.join(results), end="")
2025-07-02 06:41:18.676         - abcDefghiJkl
2025-07-02 06:41:18.676         + abcdefGhijkl
2025-07-02 06:41:18.676         """
2025-07-02 06:41:18.676
2025-07-02 06:41:18.676         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.676         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.676         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.676         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.676         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.676
2025-07-02 06:41:18.677         # search for the pair that matches best without being identical
2025-07-02 06:41:18.677         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.677         # on junk -- unless we have to)
2025-07-02 06:41:18.677         for j in range(blo, bhi):
2025-07-02 06:41:18.677             bj = b[j]
2025-07-02 06:41:18.677             cruncher.set_seq2(bj)
2025-07-02 06:41:18.677             for i in range(alo, ahi):
2025-07-02 06:41:18.677                 ai = a[i]
2025-07-02 06:41:18.677                 if ai == bj:
2025-07-02 06:41:18.677                     if eqi is None:
2025-07-02 06:41:18.677                         eqi, eqj = i, j
2025-07-02 06:41:18.677                     continue
2025-07-02 06:41:18.677                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.677                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.677                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.677                 # compares by a factor of 3.
2025-07-02 06:41:18.677                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.677                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.677                 # of the computation is cached by cruncher
2025-07-02 06:41:18.677                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.678                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.678                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.678                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.678         if best_ratio < cutoff:
2025-07-02 06:41:18.678             # no non-identical "pretty close" pair
2025-07-02 06:41:18.678             if eqi is None:
2025-07-02 06:41:18.678                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.678                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.678                 return
2025-07-02 06:41:18.678             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.678             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.678         else:
2025-07-02 06:41:18.678             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.678             eqi = None
2025-07-02 06:41:18.678
2025-07-02 06:41:18.678         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.678         # identical
2025-07-02 06:41:18.678
2025-07-02 06:41:18.678         # pump out diffs from before the synch point
2025-07-02 06:41:18.679         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.679
2025-07-02 06:41:18.679         # do intraline marking on the synch pair
2025-07-02 06:41:18.679         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.679         if eqi is None:
2025-07-02 06:41:18.679             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.679             atags = btags = ""
2025-07-02 06:41:18.679             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.679             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.679                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.679                 if tag == 'replace':
2025-07-02 06:41:18.679                     atags += '^' * la
2025-07-02 06:41:18.679                     btags += '^' * lb
2025-07-02 06:41:18.679                 elif tag == 'delete':
2025-07-02 06:41:18.679                     atags += '-' * la
2025-07-02 06:41:18.679                 elif tag == 'insert':
2025-07-02 06:41:18.679                     btags += '+' * lb
2025-07-02 06:41:18.679                 elif tag == 'equal':
2025-07-02 06:41:18.679                     atags += ' ' * la
2025-07-02 06:41:18.679                     btags += ' ' * lb
2025-07-02 06:41:18.679                 else:
2025-07-02 06:41:18.680                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.680             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.680         else:
2025-07-02 06:41:18.680             # the synch pair is identical
2025-07-02 06:41:18.680             yield '  ' + aelt
2025-07-02 06:41:18.680
2025-07-02 06:41:18.680         # pump out diffs from after the synch point
2025-07-02 06:41:18.680 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.680
2025-07-02 06:41:18.680 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.680 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.680
2025-07-02 06:41:18.680 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.680 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.680 alo = 440, ahi = 1101
2025-07-02 06:41:18.680 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.680 blo = 440, bhi = 1101
2025-07-02 06:41:18.680
2025-07-02 06:41:18.680     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.680         g = []
2025-07-02 06:41:18.681         if alo < ahi:
2025-07-02 06:41:18.681             if blo < bhi:
2025-07-02 06:41:18.681                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.681             else:
2025-07-02 06:41:18.681                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.681         elif blo < bhi:
2025-07-02 06:41:18.681             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.681
2025-07-02 06:41:18.681 >       yield from g
2025-07-02 06:41:18.681
2025-07-02 06:41:18.681 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.681 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.681
2025-07-02 06:41:18.681 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.681 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.681 alo = 440, ahi = 1101
2025-07-02 06:41:18.681 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.681 blo = 440, bhi = 1101
2025-07-02 06:41:18.681
2025-07-02 06:41:18.681     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.682         r"""
2025-07-02 06:41:18.682         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.682         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.682         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.682         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.682
2025-07-02 06:41:18.682         Example:
2025-07-02 06:41:18.682
2025-07-02 06:41:18.682         >>> d = Differ()
2025-07-02 06:41:18.682         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.682         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.682         >>> print(''.join(results), end="")
2025-07-02 06:41:18.682         - abcDefghiJkl
2025-07-02 06:41:18.682         + abcdefGhijkl
2025-07-02 06:41:18.682         """
2025-07-02 06:41:18.682
2025-07-02 06:41:18.682         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.682         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.683         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.683         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.683         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.683
2025-07-02 06:41:18.683         # search for the pair that matches best without being identical
2025-07-02 06:41:18.683         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.683         # on junk -- unless we have to)
2025-07-02 06:41:18.683         for j in range(blo, bhi):
2025-07-02 06:41:18.683             bj = b[j]
2025-07-02 06:41:18.683             cruncher.set_seq2(bj)
2025-07-02 06:41:18.683             for i in range(alo, ahi):
2025-07-02 06:41:18.683                 ai = a[i]
2025-07-02 06:41:18.683                 if ai == bj:
2025-07-02 06:41:18.683                     if eqi is None:
2025-07-02 06:41:18.683                         eqi, eqj = i, j
2025-07-02 06:41:18.683                     continue
2025-07-02 06:41:18.683                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.683                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.683                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.683                 # compares by a factor of 3.
2025-07-02 06:41:18.683                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.684                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.684                 # of the computation is cached by cruncher
2025-07-02 06:41:18.684                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.684                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.684                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.684                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.684         if best_ratio < cutoff:
2025-07-02 06:41:18.684             # no non-identical "pretty close" pair
2025-07-02 06:41:18.684             if eqi is None:
2025-07-02 06:41:18.684                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.684                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.684                 return
2025-07-02 06:41:18.684             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.684             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.684         else:
2025-07-02 06:41:18.684             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.684             eqi = None
2025-07-02 06:41:18.684
2025-07-02 06:41:18.684         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.684         # identical
2025-07-02 06:41:18.685
2025-07-02 06:41:18.685         # pump out diffs from before the synch point
2025-07-02 06:41:18.685         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.685
2025-07-02 06:41:18.685         # do intraline marking on the synch pair
2025-07-02 06:41:18.685         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.685         if eqi is None:
2025-07-02 06:41:18.685             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.685             atags = btags = ""
2025-07-02 06:41:18.685             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.685             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.685                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.685                 if tag == 'replace':
2025-07-02 06:41:18.685                     atags += '^' * la
2025-07-02 06:41:18.685                     btags += '^' * lb
2025-07-02 06:41:18.685                 elif tag == 'delete':
2025-07-02 06:41:18.685                     atags += '-' * la
2025-07-02 06:41:18.685                 elif tag == 'insert':
2025-07-02 06:41:18.685                     btags += '+' * lb
2025-07-02 06:41:18.686                 elif tag == 'equal':
2025-07-02 06:41:18.686                     atags += ' ' * la
2025-07-02 06:41:18.686                     btags += ' ' * lb
2025-07-02 06:41:18.686                 else:
2025-07-02 06:41:18.686                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.686             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.686         else:
2025-07-02 06:41:18.686             # the synch pair is identical
2025-07-02 06:41:18.686             yield '  ' + aelt
2025-07-02 06:41:18.686
2025-07-02 06:41:18.686         # pump out diffs from after the synch point
2025-07-02 06:41:18.686 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.686
2025-07-02 06:41:18.686 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.686 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.686
2025-07-02 06:41:18.686 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.686 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.686 alo = 441, ahi = 1101
2025-07-02 06:41:18.686 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.687 blo = 441, bhi = 1101
2025-07-02 06:41:18.687
2025-07-02 06:41:18.687     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.687         g = []
2025-07-02 06:41:18.687         if alo < ahi:
2025-07-02 06:41:18.687             if blo < bhi:
2025-07-02 06:41:18.687                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.687             else:
2025-07-02 06:41:18.687                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.687         elif blo < bhi:
2025-07-02 06:41:18.687             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.687
2025-07-02 06:41:18.687 >       yield from g
2025-07-02 06:41:18.687
2025-07-02 06:41:18.687 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.687 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.687
2025-07-02 06:41:18.687 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.687 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.688 alo = 441, ahi = 1101
2025-07-02 06:41:18.688 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.688 blo = 441, bhi = 1101
2025-07-02 06:41:18.688
2025-07-02 06:41:18.688     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.688         r"""
2025-07-02 06:41:18.688         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.688         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.688         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.688         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.688
2025-07-02 06:41:18.688         Example:
2025-07-02 06:41:18.688
2025-07-02 06:41:18.688         >>> d = Differ()
2025-07-02 06:41:18.688         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.688         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.688         >>> print(''.join(results), end="")
2025-07-02 06:41:18.688         - abcDefghiJkl
2025-07-02 06:41:18.688         + abcdefGhijkl
2025-07-02 06:41:18.689         """
2025-07-02 06:41:18.689
2025-07-02 06:41:18.689         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.689         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.689         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.689         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.689         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.689
2025-07-02 06:41:18.689         # search for the pair that matches best without being identical
2025-07-02 06:41:18.689         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.689         # on junk -- unless we have to)
2025-07-02 06:41:18.689         for j in range(blo, bhi):
2025-07-02 06:41:18.689             bj = b[j]
2025-07-02 06:41:18.689             cruncher.set_seq2(bj)
2025-07-02 06:41:18.689             for i in range(alo, ahi):
2025-07-02 06:41:18.689                 ai = a[i]
2025-07-02 06:41:18.689                 if ai == bj:
2025-07-02 06:41:18.690                     if eqi is None:
2025-07-02 06:41:18.690                         eqi, eqj = i, j
2025-07-02 06:41:18.690                     continue
2025-07-02 06:41:18.690                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.690                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.690                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.690                 # compares by a factor of 3.
2025-07-02 06:41:18.690                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.690                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.690                 # of the computation is cached by cruncher
2025-07-02 06:41:18.690                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.690                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.690                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.690                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.690         if best_ratio < cutoff:
2025-07-02 06:41:18.690             # no non-identical "pretty close" pair
2025-07-02 06:41:18.690             if eqi is None:
2025-07-02 06:41:18.690                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.690                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.690                 return
2025-07-02 06:41:18.691             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.691             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.691         else:
2025-07-02 06:41:18.691             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.691             eqi = None
2025-07-02 06:41:18.691
2025-07-02 06:41:18.691         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.691         # identical
2025-07-02 06:41:18.691
2025-07-02 06:41:18.691         # pump out diffs from before the synch point
2025-07-02 06:41:18.691         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.691
2025-07-02 06:41:18.691         # do intraline marking on the synch pair
2025-07-02 06:41:18.691         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.691         if eqi is None:
2025-07-02 06:41:18.691             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.691             atags = btags = ""
2025-07-02 06:41:18.691             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.691             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.691                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.692                 if tag == 'replace':
2025-07-02 06:41:18.692                     atags += '^' * la
2025-07-02 06:41:18.692                     btags += '^' * lb
2025-07-02 06:41:18.692                 elif tag == 'delete':
2025-07-02 06:41:18.692                     atags += '-' * la
2025-07-02 06:41:18.692                 elif tag == 'insert':
2025-07-02 06:41:18.692                     btags += '+' * lb
2025-07-02 06:41:18.692                 elif tag == 'equal':
2025-07-02 06:41:18.692                     atags += ' ' * la
2025-07-02 06:41:18.692                     btags += ' ' * lb
2025-07-02 06:41:18.692                 else:
2025-07-02 06:41:18.692                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.692             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.692         else:
2025-07-02 06:41:18.692             # the synch pair is identical
2025-07-02 06:41:18.692             yield '  ' + aelt
2025-07-02 06:41:18.692
2025-07-02 06:41:18.692         # pump out diffs from after the synch point
2025-07-02 06:41:18.692 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.692
2025-07-02 06:41:18.692 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.693 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.693
2025-07-02 06:41:18.693 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.693 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.693 alo = 444, ahi = 1101
2025-07-02 06:41:18.693 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.693 blo = 444, bhi = 1101
2025-07-02 06:41:18.693
2025-07-02 06:41:18.693     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.693         g = []
2025-07-02 06:41:18.693         if alo < ahi:
2025-07-02 06:41:18.693             if blo < bhi:
2025-07-02 06:41:18.693                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.693             else:
2025-07-02 06:41:18.693                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.693         elif blo < bhi:
2025-07-02 06:41:18.693             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.693
2025-07-02 06:41:18.693 >       yield from g
2025-07-02 06:41:18.693
2025-07-02 06:41:18.694 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.694 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.694
2025-07-02 06:41:18.694 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.694 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.694 alo = 444, ahi = 1101
2025-07-02 06:41:18.694 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.694 blo = 444, bhi = 1101
2025-07-02 06:41:18.694
2025-07-02 06:41:18.694     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.694         r"""
2025-07-02 06:41:18.694         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.694         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.694         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.694         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.694
2025-07-02 06:41:18.694         Example:
2025-07-02 06:41:18.694
2025-07-02 06:41:18.695         >>> d = Differ()
2025-07-02 06:41:18.695         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.695         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.695         >>> print(''.join(results), end="")
2025-07-02 06:41:18.695         - abcDefghiJkl
2025-07-02 06:41:18.695         + abcdefGhijkl
2025-07-02 06:41:18.695         """
2025-07-02 06:41:18.695
2025-07-02 06:41:18.695         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.695         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.695         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.695         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.695         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.695
2025-07-02 06:41:18.695         # search for the pair that matches best without being identical
2025-07-02 06:41:18.695         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.695         # on junk -- unless we have to)
2025-07-02 06:41:18.696         for j in range(blo, bhi):
2025-07-02 06:41:18.696             bj = b[j]
2025-07-02 06:41:18.696             cruncher.set_seq2(bj)
2025-07-02 06:41:18.696             for i in range(alo, ahi):
2025-07-02 06:41:18.696                 ai = a[i]
2025-07-02 06:41:18.696                 if ai == bj:
2025-07-02 06:41:18.696                     if eqi is None:
2025-07-02 06:41:18.696                         eqi, eqj = i, j
2025-07-02 06:41:18.696                     continue
2025-07-02 06:41:18.696                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.696                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.696                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.696                 # compares by a factor of 3.
2025-07-02 06:41:18.696                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.696                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.696                 # of the computation is cached by cruncher
2025-07-02 06:41:18.696                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.696                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.696                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.696                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.697         if best_ratio < cutoff:
2025-07-02 06:41:18.697             # no non-identical "pretty close" pair
2025-07-02 06:41:18.697             if eqi is None:
2025-07-02 06:41:18.697                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.697                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.697                 return
2025-07-02 06:41:18.697             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.697             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.697         else:
2025-07-02 06:41:18.697             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.697             eqi = None
2025-07-02 06:41:18.697
2025-07-02 06:41:18.697         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.697         # identical
2025-07-02 06:41:18.697
2025-07-02 06:41:18.697         # pump out diffs from before the synch point
2025-07-02 06:41:18.697         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.697
2025-07-02 06:41:18.697         # do intraline marking on the synch pair
2025-07-02 06:41:18.697         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.698         if eqi is None:
2025-07-02 06:41:18.698             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.698             atags = btags = ""
2025-07-02 06:41:18.698             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.698             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.698                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.698                 if tag == 'replace':
2025-07-02 06:41:18.698                     atags += '^' * la
2025-07-02 06:41:18.698                     btags += '^' * lb
2025-07-02 06:41:18.698                 elif tag == 'delete':
2025-07-02 06:41:18.698                     atags += '-' * la
2025-07-02 06:41:18.698                 elif tag == 'insert':
2025-07-02 06:41:18.698                     btags += '+' * lb
2025-07-02 06:41:18.698                 elif tag == 'equal':
2025-07-02 06:41:18.698                     atags += ' ' * la
2025-07-02 06:41:18.698                     btags += ' ' * lb
2025-07-02 06:41:18.698                 else:
2025-07-02 06:41:18.698                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.698             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.698         else:
2025-07-02 06:41:18.698             # the synch pair is identical
2025-07-02 06:41:18.699             yield '  ' + aelt
2025-07-02 06:41:18.699
2025-07-02 06:41:18.699         # pump out diffs from after the synch point
2025-07-02 06:41:18.699 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.699
2025-07-02 06:41:18.699 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.699 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.699
2025-07-02 06:41:18.699 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.699 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.699 alo = 445, ahi = 1101
2025-07-02 06:41:18.699 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.699 blo = 445, bhi = 1101
2025-07-02 06:41:18.699
2025-07-02 06:41:18.699     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.699         g = []
2025-07-02 06:41:18.699         if alo < ahi:
2025-07-02 06:41:18.699             if blo < bhi:
2025-07-02 06:41:18.699                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.699             else:
2025-07-02 06:41:18.700                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.700         elif blo < bhi:
2025-07-02 06:41:18.700             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.700
2025-07-02 06:41:18.700 >       yield from g
2025-07-02 06:41:18.700
2025-07-02 06:41:18.700 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.700 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.700
2025-07-02 06:41:18.700 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.700 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.700 alo = 445, ahi = 1101
2025-07-02 06:41:18.700 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.700 blo = 445, bhi = 1101
2025-07-02 06:41:18.700
2025-07-02 06:41:18.700     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.700         r"""
2025-07-02 06:41:18.700         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.700         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.700         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.701         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.701
2025-07-02 06:41:18.701         Example:
2025-07-02 06:41:18.701
2025-07-02 06:41:18.701         >>> d = Differ()
2025-07-02 06:41:18.701         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.701         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.701         >>> print(''.join(results), end="")
2025-07-02 06:41:18.701         - abcDefghiJkl
2025-07-02 06:41:18.701         + abcdefGhijkl
2025-07-02 06:41:18.701         """
2025-07-02 06:41:18.701
2025-07-02 06:41:18.701         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.701         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.701         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.701         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.701         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.701
2025-07-02 06:41:18.702         # search for the pair that matches best without being identical
2025-07-02 06:41:18.702         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.702         # on junk -- unless we have to)
2025-07-02 06:41:18.702         for j in range(blo, bhi):
2025-07-02 06:41:18.702             bj = b[j]
2025-07-02 06:41:18.702             cruncher.set_seq2(bj)
2025-07-02 06:41:18.702             for i in range(alo, ahi):
2025-07-02 06:41:18.702                 ai = a[i]
2025-07-02 06:41:18.702                 if ai == bj:
2025-07-02 06:41:18.702                     if eqi is None:
2025-07-02 06:41:18.702                         eqi, eqj = i, j
2025-07-02 06:41:18.702                     continue
2025-07-02 06:41:18.702                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.702                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.702                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.702                 # compares by a factor of 3.
2025-07-02 06:41:18.702                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.702                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.702                 # of the computation is cached by cruncher
2025-07-02 06:41:18.703                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.703                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.703                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.703                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.703         if best_ratio < cutoff:
2025-07-02 06:41:18.703             # no non-identical "pretty close" pair
2025-07-02 06:41:18.703             if eqi is None:
2025-07-02 06:41:18.703                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.703                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.703                 return
2025-07-02 06:41:18.703             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.703             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.703         else:
2025-07-02 06:41:18.703             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.703             eqi = None
2025-07-02 06:41:18.703
2025-07-02 06:41:18.703         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.703         # identical
2025-07-02 06:41:18.703
2025-07-02 06:41:18.704         # pump out diffs from before the synch point
2025-07-02 06:41:18.704         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.704
2025-07-02 06:41:18.704         # do intraline marking on the synch pair
2025-07-02 06:41:18.704         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.704         if eqi is None:
2025-07-02 06:41:18.704             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.704             atags = btags = ""
2025-07-02 06:41:18.704             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.704             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.704                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.704                 if tag == 'replace':
2025-07-02 06:41:18.704                     atags += '^' * la
2025-07-02 06:41:18.704                     btags += '^' * lb
2025-07-02 06:41:18.704                 elif tag == 'delete':
2025-07-02 06:41:18.704                     atags += '-' * la
2025-07-02 06:41:18.704                 elif tag == 'insert':
2025-07-02 06:41:18.704                     btags += '+' * lb
2025-07-02 06:41:18.704                 elif tag == 'equal':
2025-07-02 06:41:18.704                     atags += ' ' * la
2025-07-02 06:41:18.705                     btags += ' ' * lb
2025-07-02 06:41:18.705                 else:
2025-07-02 06:41:18.705                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.705             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.705         else:
2025-07-02 06:41:18.705             # the synch pair is identical
2025-07-02 06:41:18.705             yield '  ' + aelt
2025-07-02 06:41:18.705
2025-07-02 06:41:18.705         # pump out diffs from after the synch point
2025-07-02 06:41:18.705 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.705
2025-07-02 06:41:18.705 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.705 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.705
2025-07-02 06:41:18.705 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.705 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.705 alo = 446, ahi = 1101
2025-07-02 06:41:18.706 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.706 blo = 446, bhi = 1101
2025-07-02 06:41:18.706
2025-07-02 06:41:18.706     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.706         g = []
2025-07-02 06:41:18.706         if alo < ahi:
2025-07-02 06:41:18.706             if blo < bhi:
2025-07-02 06:41:18.706                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.706             else:
2025-07-02 06:41:18.706                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.706         elif blo < bhi:
2025-07-02 06:41:18.706             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.706
2025-07-02 06:41:18.706 >       yield from g
2025-07-02 06:41:18.706
2025-07-02 06:41:18.706 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.706 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.706
2025-07-02 06:41:18.706 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.707 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.707 alo = 446, ahi = 1101
2025-07-02 06:41:18.707 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.707 blo = 446, bhi = 1101
2025-07-02 06:41:18.707
2025-07-02 06:41:18.707     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.707         r"""
2025-07-02 06:41:18.707         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.707         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.707         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.707         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.707
2025-07-02 06:41:18.707         Example:
2025-07-02 06:41:18.707
2025-07-02 06:41:18.707         >>> d = Differ()
2025-07-02 06:41:18.707         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.707         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.708         >>> print(''.join(results), end="")
2025-07-02 06:41:18.708         - abcDefghiJkl
2025-07-02 06:41:18.708         + abcdefGhijkl
2025-07-02 06:41:18.708         """
2025-07-02 06:41:18.708
2025-07-02 06:41:18.708         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.708         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.708         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.708         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.708         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.708
2025-07-02 06:41:18.708         # search for the pair that matches best without being identical
2025-07-02 06:41:18.708         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.708         # on junk -- unless we have to)
2025-07-02 06:41:18.709         for j in range(blo, bhi):
2025-07-02 06:41:18.709             bj = b[j]
2025-07-02 06:41:18.709             cruncher.set_seq2(bj)
2025-07-02 06:41:18.709             for i in range(alo, ahi):
2025-07-02 06:41:18.709                 ai = a[i]
2025-07-02 06:41:18.709                 if ai == bj:
2025-07-02 06:41:18.709                     if eqi is None:
2025-07-02 06:41:18.709                         eqi, eqj = i, j
2025-07-02 06:41:18.709                     continue
2025-07-02 06:41:18.709                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.709                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.709                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.709                 # compares by a factor of 3.
2025-07-02 06:41:18.709                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.709                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.710                 # of the computation is cached by cruncher
2025-07-02 06:41:18.710                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.710                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.710                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.710                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.710         if best_ratio < cutoff:
2025-07-02 06:41:18.710             # no non-identical "pretty close" pair
2025-07-02 06:41:18.710             if eqi is None:
2025-07-02 06:41:18.710                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.710                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.710                 return
2025-07-02 06:41:18.710             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.710             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.710         else:
2025-07-02 06:41:18.710             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.710             eqi = None
2025-07-02 06:41:18.711
2025-07-02 06:41:18.711         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.711         # identical
2025-07-02 06:41:18.711
2025-07-02 06:41:18.711         # pump out diffs from before the synch point
2025-07-02 06:41:18.711         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.711
2025-07-02 06:41:18.711         # do intraline marking on the synch pair
2025-07-02 06:41:18.711         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.711         if eqi is None:
2025-07-02 06:41:18.711             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.711             atags = btags = ""
2025-07-02 06:41:18.711             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.711             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.711                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.711                 if tag == 'replace':
2025-07-02 06:41:18.712                     atags += '^' * la
2025-07-02 06:41:18.712                     btags += '^' * lb
2025-07-02 06:41:18.712                 elif tag == 'delete':
2025-07-02 06:41:18.712                     atags += '-' * la
2025-07-02 06:41:18.712                 elif tag == 'insert':
2025-07-02 06:41:18.712                     btags += '+' * lb
2025-07-02 06:41:18.712                 elif tag == 'equal':
2025-07-02 06:41:18.712                     atags += ' ' * la
2025-07-02 06:41:18.712                     btags += ' ' * lb
2025-07-02 06:41:18.712                 else:
2025-07-02 06:41:18.712                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.712             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.712         else:
2025-07-02 06:41:18.712             # the synch pair is identical
2025-07-02 06:41:18.712             yield '  ' + aelt
2025-07-02 06:41:18.712
2025-07-02 06:41:18.713         # pump out diffs from after the synch point
2025-07-02 06:41:18.713 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.713
2025-07-02 06:41:18.713 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.713 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.713
2025-07-02 06:41:18.713 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.713 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.713 alo = 447, ahi = 1101
2025-07-02 06:41:18.713 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.713 blo = 447, bhi = 1101
2025-07-02 06:41:18.713
2025-07-02 06:41:18.713     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.713         g = []
2025-07-02 06:41:18.713         if alo < ahi:
2025-07-02 06:41:18.713             if blo < bhi:
2025-07-02 06:41:18.714                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.714             else:
2025-07-02 06:41:18.714                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.714         elif blo < bhi:
2025-07-02 06:41:18.714             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.714
2025-07-02 06:41:18.714 >       yield from g
2025-07-02 06:41:18.714
2025-07-02 06:41:18.714 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.714 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.714
2025-07-02 06:41:18.714 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.714 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.714 alo = 447, ahi = 1101
2025-07-02 06:41:18.714 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.715 blo = 447, bhi = 1101
2025-07-02 06:41:18.715
2025-07-02 06:41:18.715     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.715         r"""
2025-07-02 06:41:18.715         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.715         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.715         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.715         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.715
2025-07-02 06:41:18.715         Example:
2025-07-02 06:41:18.715
2025-07-02 06:41:18.715         >>> d = Differ()
2025-07-02 06:41:18.715         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.715         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.715         >>> print(''.join(results), end="")
2025-07-02 06:41:18.715         - abcDefghiJkl
2025-07-02 06:41:18.716         + abcdefGhijkl
2025-07-02 06:41:18.716         """
2025-07-02 06:41:18.716
2025-07-02 06:41:18.716         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.716         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.716         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.716         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.716         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.716
2025-07-02 06:41:18.716         # search for the pair that matches best without being identical
2025-07-02 06:41:18.716         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.716         # on junk -- unless we have to)
2025-07-02 06:41:18.716         for j in range(blo, bhi):
2025-07-02 06:41:18.716             bj = b[j]
2025-07-02 06:41:18.717             cruncher.set_seq2(bj)
2025-07-02 06:41:18.717             for i in range(alo, ahi):
2025-07-02 06:41:18.717                 ai = a[i]
2025-07-02 06:41:18.717                 if ai == bj:
2025-07-02 06:41:18.717                     if eqi is None:
2025-07-02 06:41:18.717                         eqi, eqj = i, j
2025-07-02 06:41:18.717                     continue
2025-07-02 06:41:18.717                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.717                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.717                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.717                 # compares by a factor of 3.
2025-07-02 06:41:18.717                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.717                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.717                 # of the computation is cached by cruncher
2025-07-02 06:41:18.717                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.717                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.718                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.718                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.718         if best_ratio < cutoff:
2025-07-02 06:41:18.718             # no non-identical "pretty close" pair
2025-07-02 06:41:18.718             if eqi is None:
2025-07-02 06:41:18.718                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.718                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.718                 return
2025-07-02 06:41:18.718             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.718             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.718         else:
2025-07-02 06:41:18.718             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.718             eqi = None
2025-07-02 06:41:18.718
2025-07-02 06:41:18.718         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.718         # identical
2025-07-02 06:41:18.719
2025-07-02 06:41:18.719         # pump out diffs from before the synch point
2025-07-02 06:41:18.719         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.719
2025-07-02 06:41:18.719         # do intraline marking on the synch pair
2025-07-02 06:41:18.719         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.719         if eqi is None:
2025-07-02 06:41:18.719             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.719             atags = btags = ""
2025-07-02 06:41:18.719             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.719             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.719                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.719                 if tag == 'replace':
2025-07-02 06:41:18.719                     atags += '^' * la
2025-07-02 06:41:18.719                     btags += '^' * lb
2025-07-02 06:41:18.719                 elif tag == 'delete':
2025-07-02 06:41:18.720                     atags += '-' * la
2025-07-02 06:41:18.720                 elif tag == 'insert':
2025-07-02 06:41:18.720                     btags += '+' * lb
2025-07-02 06:41:18.720                 elif tag == 'equal':
2025-07-02 06:41:18.720                     atags += ' ' * la
2025-07-02 06:41:18.720                     btags += ' ' * lb
2025-07-02 06:41:18.720                 else:
2025-07-02 06:41:18.720                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.720             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.720         else:
2025-07-02 06:41:18.720             # the synch pair is identical
2025-07-02 06:41:18.720             yield '  ' + aelt
2025-07-02 06:41:18.720
2025-07-02 06:41:18.720         # pump out diffs from after the synch point
2025-07-02 06:41:18.720 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.721
2025-07-02 06:41:18.721 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.721 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.721
2025-07-02 06:41:18.721 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.721 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.721 alo = 448, ahi = 1101
2025-07-02 06:41:18.721 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.721 blo = 448, bhi = 1101
2025-07-02 06:41:18.721
2025-07-02 06:41:18.721     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.721         g = []
2025-07-02 06:41:18.721         if alo < ahi:
2025-07-02 06:41:18.721             if blo < bhi:
2025-07-02 06:41:18.722                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.722             else:
2025-07-02 06:41:18.722                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.722         elif blo < bhi:
2025-07-02 06:41:18.722             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.722
2025-07-02 06:41:18.722 >       yield from g
2025-07-02 06:41:18.722
2025-07-02 06:41:18.722 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.722 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.722
2025-07-02 06:41:18.722 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.722 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.722 alo = 448, ahi = 1101
2025-07-02 06:41:18.722 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.722 blo = 448, bhi = 1101
2025-07-02 06:41:18.723
2025-07-02 06:41:18.723     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.723         r"""
2025-07-02 06:41:18.723         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.723         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.723         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.723         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.723
2025-07-02 06:41:18.723         Example:
2025-07-02 06:41:18.723
2025-07-02 06:41:18.723         >>> d = Differ()
2025-07-02 06:41:18.723         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.723         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.723         >>> print(''.join(results), end="")
2025-07-02 06:41:18.723         - abcDefghiJkl
2025-07-02 06:41:18.724         + abcdefGhijkl
2025-07-02 06:41:18.724         """
2025-07-02 06:41:18.724
2025-07-02 06:41:18.724         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.724         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.724         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.724         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.724         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.724
2025-07-02 06:41:18.724         # search for the pair that matches best without being identical
2025-07-02 06:41:18.724         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.724         # on junk -- unless we have to)
2025-07-02 06:41:18.724         for j in range(blo, bhi):
2025-07-02 06:41:18.724             bj = b[j]
2025-07-02 06:41:18.724             cruncher.set_seq2(bj)
2025-07-02 06:41:18.725             for i in range(alo, ahi):
2025-07-02 06:41:18.725                 ai = a[i]
2025-07-02 06:41:18.725                 if ai == bj:
2025-07-02 06:41:18.725                     if eqi is None:
2025-07-02 06:41:18.725                         eqi, eqj = i, j
2025-07-02 06:41:18.725                     continue
2025-07-02 06:41:18.725                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.725                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.725                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.725                 # compares by a factor of 3.
2025-07-02 06:41:18.725                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.725                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.725                 # of the computation is cached by cruncher
2025-07-02 06:41:18.725                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.725                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.725                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.726                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.726         if best_ratio < cutoff:
2025-07-02 06:41:18.726             # no non-identical "pretty close" pair
2025-07-02 06:41:18.726             if eqi is None:
2025-07-02 06:41:18.726                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.726                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.726                 return
2025-07-02 06:41:18.726             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.726             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.726         else:
2025-07-02 06:41:18.726             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.726             eqi = None
2025-07-02 06:41:18.726
2025-07-02 06:41:18.726         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.726         # identical
2025-07-02 06:41:18.726
2025-07-02 06:41:18.727         # pump out diffs from before the synch point
2025-07-02 06:41:18.727         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.727
2025-07-02 06:41:18.727         # do intraline marking on the synch pair
2025-07-02 06:41:18.727         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.727         if eqi is None:
2025-07-02 06:41:18.727             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.727             atags = btags = ""
2025-07-02 06:41:18.727             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.727             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.727                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.727                 if tag == 'replace':
2025-07-02 06:41:18.727                     atags += '^' * la
2025-07-02 06:41:18.727                     btags += '^' * lb
2025-07-02 06:41:18.727                 elif tag == 'delete':
2025-07-02 06:41:18.727                     atags += '-' * la
2025-07-02 06:41:18.727                 elif tag == 'insert':
2025-07-02 06:41:18.727                     btags += '+' * lb
2025-07-02 06:41:18.728                 elif tag == 'equal':
2025-07-02 06:41:18.728                     atags += ' ' * la
2025-07-02 06:41:18.728                     btags += ' ' * lb
2025-07-02 06:41:18.728                 else:
2025-07-02 06:41:18.728                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.728             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.728         else:
2025-07-02 06:41:18.728             # the synch pair is identical
2025-07-02 06:41:18.728             yield '  ' + aelt
2025-07-02 06:41:18.728
2025-07-02 06:41:18.728         # pump out diffs from after the synch point
2025-07-02 06:41:18.728 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.728
2025-07-02 06:41:18.728 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.728 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.728
2025-07-02 06:41:18.728 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.728 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.728 alo = 449, ahi = 1101
2025-07-02 06:41:18.729 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.729 blo = 449, bhi = 1101
2025-07-02 06:41:18.729
2025-07-02 06:41:18.729     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.729         g = []
2025-07-02 06:41:18.729         if alo < ahi:
2025-07-02 06:41:18.729             if blo < bhi:
2025-07-02 06:41:18.729                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.729             else:
2025-07-02 06:41:18.729                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.729         elif blo < bhi:
2025-07-02 06:41:18.729             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.729
2025-07-02 06:41:18.729 >       yield from g
2025-07-02 06:41:18.729
2025-07-02 06:41:18.729 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.729 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.729
2025-07-02 06:41:18.729 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.730 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.730 alo = 449, ahi = 1101
2025-07-02 06:41:18.730 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.730 blo = 449, bhi = 1101
2025-07-02 06:41:18.730
2025-07-02 06:41:18.730     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.730         r"""
2025-07-02 06:41:18.730         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.730         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.730         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.730         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.730
2025-07-02 06:41:18.730         Example:
2025-07-02 06:41:18.730
2025-07-02 06:41:18.730         >>> d = Differ()
2025-07-02 06:41:18.730         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.730         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.730         >>> print(''.join(results), end="")
2025-07-02 06:41:18.730         - abcDefghiJkl
2025-07-02 06:41:18.731         + abcdefGhijkl
2025-07-02 06:41:18.731         """
2025-07-02 06:41:18.731
2025-07-02 06:41:18.731         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.731         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.731         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.731         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.731         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.731
2025-07-02 06:41:18.731         # search for the pair that matches best without being identical
2025-07-02 06:41:18.731         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.731         # on junk -- unless we have to)
2025-07-02 06:41:18.731         for j in range(blo, bhi):
2025-07-02 06:41:18.731             bj = b[j]
2025-07-02 06:41:18.731             cruncher.set_seq2(bj)
2025-07-02 06:41:18.731             for i in range(alo, ahi):
2025-07-02 06:41:18.731                 ai = a[i]
2025-07-02 06:41:18.732                 if ai == bj:
2025-07-02 06:41:18.732                     if eqi is None:
2025-07-02 06:41:18.732                         eqi, eqj = i, j
2025-07-02 06:41:18.732                     continue
2025-07-02 06:41:18.732                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.732                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.732                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.732                 # compares by a factor of 3.
2025-07-02 06:41:18.732                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.732                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.732                 # of the computation is cached by cruncher
2025-07-02 06:41:18.732                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.732                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.732                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.732                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.732         if best_ratio < cutoff:
2025-07-02 06:41:18.732             # no non-identical "pretty close" pair
2025-07-02 06:41:18.732             if eqi is None:
2025-07-02 06:41:18.732                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.733                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.733                 return
2025-07-02 06:41:18.733             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.733             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.733         else:
2025-07-02 06:41:18.733             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.733             eqi = None
2025-07-02 06:41:18.733
2025-07-02 06:41:18.733         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.733         # identical
2025-07-02 06:41:18.733
2025-07-02 06:41:18.733         # pump out diffs from before the synch point
2025-07-02 06:41:18.733         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.733
2025-07-02 06:41:18.733         # do intraline marking on the synch pair
2025-07-02 06:41:18.733         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.733         if eqi is None:
2025-07-02 06:41:18.733             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.734             atags = btags = ""
2025-07-02 06:41:18.734             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.734             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.734                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.734                 if tag == 'replace':
2025-07-02 06:41:18.734                     atags += '^' * la
2025-07-02 06:41:18.734                     btags += '^' * lb
2025-07-02 06:41:18.734                 elif tag == 'delete':
2025-07-02 06:41:18.734                     atags += '-' * la
2025-07-02 06:41:18.734                 elif tag == 'insert':
2025-07-02 06:41:18.734                     btags += '+' * lb
2025-07-02 06:41:18.734                 elif tag == 'equal':
2025-07-02 06:41:18.734                     atags += ' ' * la
2025-07-02 06:41:18.734                     btags += ' ' * lb
2025-07-02 06:41:18.734                 else:
2025-07-02 06:41:18.734                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.734             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.734         else:
2025-07-02 06:41:18.734             # the synch pair is identical
2025-07-02 06:41:18.734             yield '  ' + aelt
2025-07-02 06:41:18.735
2025-07-02 06:41:18.735         # pump out diffs from after the synch point
2025-07-02 06:41:18.735 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.735
2025-07-02 06:41:18.735 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.735 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.735
2025-07-02 06:41:18.735 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.735 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.735 alo = 450, ahi = 1101
2025-07-02 06:41:18.735 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.735 blo = 450, bhi = 1101
2025-07-02 06:41:18.735
2025-07-02 06:41:18.735     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.735         g = []
2025-07-02 06:41:18.735         if alo < ahi:
2025-07-02 06:41:18.735             if blo < bhi:
2025-07-02 06:41:18.735                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.736             else:
2025-07-02 06:41:18.736                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.736         elif blo < bhi:
2025-07-02 06:41:18.736             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.736
2025-07-02 06:41:18.736 >       yield from g
2025-07-02 06:41:18.736
2025-07-02 06:41:18.736 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.736 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.736
2025-07-02 06:41:18.736 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.736 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.736 alo = 450, ahi = 1101
2025-07-02 06:41:18.736 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.736 blo = 450, bhi = 1101
2025-07-02 06:41:18.737
2025-07-02 06:41:18.737     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.737         r"""
2025-07-02 06:41:18.737         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.737         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.737         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.737         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.737
2025-07-02 06:41:18.737         Example:
2025-07-02 06:41:18.737
2025-07-02 06:41:18.737         >>> d = Differ()
2025-07-02 06:41:18.737         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.737         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.737         >>> print(''.join(results), end="")
2025-07-02 06:41:18.737         - abcDefghiJkl
2025-07-02 06:41:18.737         + abcdefGhijkl
2025-07-02 06:41:18.738         """
2025-07-02 06:41:18.738
2025-07-02 06:41:18.738         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.738         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.738         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.738         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.738         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.738
2025-07-02 06:41:18.738         # search for the pair that matches best without being identical
2025-07-02 06:41:18.738         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.738         # on junk -- unless we have to)
2025-07-02 06:41:18.738         for j in range(blo, bhi):
2025-07-02 06:41:18.738             bj = b[j]
2025-07-02 06:41:18.738             cruncher.set_seq2(bj)
2025-07-02 06:41:18.738             for i in range(alo, ahi):
2025-07-02 06:41:18.738                 ai = a[i]
2025-07-02 06:41:18.738                 if ai == bj:
2025-07-02 06:41:18.738                     if eqi is None:
2025-07-02 06:41:18.738                         eqi, eqj = i, j
2025-07-02 06:41:18.739                     continue
2025-07-02 06:41:18.739                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.739                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.739                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.739                 # compares by a factor of 3.
2025-07-02 06:41:18.739                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.739                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.739                 # of the computation is cached by cruncher
2025-07-02 06:41:18.739                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.739                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.739                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.739                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.739         if best_ratio < cutoff:
2025-07-02 06:41:18.739             # no non-identical "pretty close" pair
2025-07-02 06:41:18.739             if eqi is None:
2025-07-02 06:41:18.739                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.739                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.739                 return
2025-07-02 06:41:18.739             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.740             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.740         else:
2025-07-02 06:41:18.740             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.740             eqi = None
2025-07-02 06:41:18.740
2025-07-02 06:41:18.740         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.740         # identical
2025-07-02 06:41:18.740
2025-07-02 06:41:18.740         # pump out diffs from before the synch point
2025-07-02 06:41:18.740         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.740
2025-07-02 06:41:18.740         # do intraline marking on the synch pair
2025-07-02 06:41:18.740         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.740         if eqi is None:
2025-07-02 06:41:18.740             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.740             atags = btags = ""
2025-07-02 06:41:18.740             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.740             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.740                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.741                 if tag == 'replace':
2025-07-02 06:41:18.741                     atags += '^' * la
2025-07-02 06:41:18.741                     btags += '^' * lb
2025-07-02 06:41:18.741                 elif tag == 'delete':
2025-07-02 06:41:18.741                     atags += '-' * la
2025-07-02 06:41:18.741                 elif tag == 'insert':
2025-07-02 06:41:18.741                     btags += '+' * lb
2025-07-02 06:41:18.741                 elif tag == 'equal':
2025-07-02 06:41:18.741                     atags += ' ' * la
2025-07-02 06:41:18.741                     btags += ' ' * lb
2025-07-02 06:41:18.741                 else:
2025-07-02 06:41:18.741                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.741             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.741         else:
2025-07-02 06:41:18.741             # the synch pair is identical
2025-07-02 06:41:18.741             yield '  ' + aelt
2025-07-02 06:41:18.741
2025-07-02 06:41:18.741         # pump out diffs from after the synch point
2025-07-02 06:41:18.741 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.741
2025-07-02 06:41:18.742 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.742 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.742
2025-07-02 06:41:18.742 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.742 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.742 alo = 451, ahi = 1101
2025-07-02 06:41:18.742 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.742 blo = 451, bhi = 1101
2025-07-02 06:41:18.742
2025-07-02 06:41:18.742     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.742         g = []
2025-07-02 06:41:18.742         if alo < ahi:
2025-07-02 06:41:18.742             if blo < bhi:
2025-07-02 06:41:18.742                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.742             else:
2025-07-02 06:41:18.742                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.742         elif blo < bhi:
2025-07-02 06:41:18.743             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.743
2025-07-02 06:41:18.743 >       yield from g
2025-07-02 06:41:18.743
2025-07-02 06:41:18.743 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.743 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.743
2025-07-02 06:41:18.743 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.743 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.743 alo = 451, ahi = 1101
2025-07-02 06:41:18.743 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.743 blo = 451, bhi = 1101
2025-07-02 06:41:18.743
2025-07-02 06:41:18.743     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.743         r"""
2025-07-02 06:41:18.743         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.743         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.743         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.743         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.744
2025-07-02 06:41:18.744         Example:
2025-07-02 06:41:18.744
2025-07-02 06:41:18.744         >>> d = Differ()
2025-07-02 06:41:18.744         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.744         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.744         >>> print(''.join(results), end="")
2025-07-02 06:41:18.744         - abcDefghiJkl
2025-07-02 06:41:18.744         + abcdefGhijkl
2025-07-02 06:41:18.744         """
2025-07-02 06:41:18.744
2025-07-02 06:41:18.744         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.744         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.744         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.744         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.744         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.744
2025-07-02 06:41:18.745         # search for the pair that matches best without being identical
2025-07-02 06:41:18.745         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.745         # on junk -- unless we have to)
2025-07-02 06:41:18.745         for j in range(blo, bhi):
2025-07-02 06:41:18.745             bj = b[j]
2025-07-02 06:41:18.745             cruncher.set_seq2(bj)
2025-07-02 06:41:18.745             for i in range(alo, ahi):
2025-07-02 06:41:18.745                 ai = a[i]
2025-07-02 06:41:18.745                 if ai == bj:
2025-07-02 06:41:18.745                     if eqi is None:
2025-07-02 06:41:18.745                         eqi, eqj = i, j
2025-07-02 06:41:18.745                     continue
2025-07-02 06:41:18.745                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.745                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.745                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.745                 # compares by a factor of 3.
2025-07-02 06:41:18.745                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.745                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.745                 # of the computation is cached by cruncher
2025-07-02 06:41:18.745                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.746                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.746                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.746                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.746         if best_ratio < cutoff:
2025-07-02 06:41:18.746             # no non-identical "pretty close" pair
2025-07-02 06:41:18.746             if eqi is None:
2025-07-02 06:41:18.746                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.746                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.746                 return
2025-07-02 06:41:18.746             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.746             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.746         else:
2025-07-02 06:41:18.746             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.746             eqi = None
2025-07-02 06:41:18.746
2025-07-02 06:41:18.746         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.746         # identical
2025-07-02 06:41:18.746
2025-07-02 06:41:18.746         # pump out diffs from before the synch point
2025-07-02 06:41:18.747         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.747
2025-07-02 06:41:18.747         # do intraline marking on the synch pair
2025-07-02 06:41:18.747         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.747         if eqi is None:
2025-07-02 06:41:18.747             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.747             atags = btags = ""
2025-07-02 06:41:18.747             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.747             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.747                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.747                 if tag == 'replace':
2025-07-02 06:41:18.747                     atags += '^' * la
2025-07-02 06:41:18.747                     btags += '^' * lb
2025-07-02 06:41:18.747                 elif tag == 'delete':
2025-07-02 06:41:18.747                     atags += '-' * la
2025-07-02 06:41:18.747                 elif tag == 'insert':
2025-07-02 06:41:18.747                     btags += '+' * lb
2025-07-02 06:41:18.747                 elif tag == 'equal':
2025-07-02 06:41:18.747                     atags += ' ' * la
2025-07-02 06:41:18.747                     btags += ' ' * lb
2025-07-02 06:41:18.748                 else:
2025-07-02 06:41:18.748                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.748             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.748         else:
2025-07-02 06:41:18.748             # the synch pair is identical
2025-07-02 06:41:18.748             yield '  ' + aelt
2025-07-02 06:41:18.748
2025-07-02 06:41:18.748         # pump out diffs from after the synch point
2025-07-02 06:41:18.748 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.748
2025-07-02 06:41:18.748 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.748 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.748
2025-07-02 06:41:18.748 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.748 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.748 alo = 452, ahi = 1101
2025-07-02 06:41:18.748 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.748 blo = 452, bhi = 1101
2025-07-02 06:41:18.749
2025-07-02 06:41:18.749     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.749         g = []
2025-07-02 06:41:18.749         if alo < ahi:
2025-07-02 06:41:18.749             if blo < bhi:
2025-07-02 06:41:18.749                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.749             else:
2025-07-02 06:41:18.749                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.749         elif blo < bhi:
2025-07-02 06:41:18.749             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.749
2025-07-02 06:41:18.749 >       yield from g
2025-07-02 06:41:18.749
2025-07-02 06:41:18.749 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.749 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.749
2025-07-02 06:41:18.749 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.749 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.749 alo = 452, ahi = 1101
2025-07-02 06:41:18.749 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.750 blo = 452, bhi = 1101
2025-07-02 06:41:18.750
2025-07-02 06:41:18.750     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.750         r"""
2025-07-02 06:41:18.750         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.750         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.750         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.750         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.750
2025-07-02 06:41:18.750         Example:
2025-07-02 06:41:18.750
2025-07-02 06:41:18.750         >>> d = Differ()
2025-07-02 06:41:18.750         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.750         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.750         >>> print(''.join(results), end="")
2025-07-02 06:41:18.750         - abcDefghiJkl
2025-07-02 06:41:18.750         + abcdefGhijkl
2025-07-02 06:41:18.751         """
2025-07-02 06:41:18.751
2025-07-02 06:41:18.751         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.751         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.751         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.751         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.751         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.751
2025-07-02 06:41:18.751         # search for the pair that matches best without being identical
2025-07-02 06:41:18.751         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.751         # on junk -- unless we have to)
2025-07-02 06:41:18.751         for j in range(blo, bhi):
2025-07-02 06:41:18.751             bj = b[j]
2025-07-02 06:41:18.751             cruncher.set_seq2(bj)
2025-07-02 06:41:18.751             for i in range(alo, ahi):
2025-07-02 06:41:18.751                 ai = a[i]
2025-07-02 06:41:18.751                 if ai == bj:
2025-07-02 06:41:18.751                     if eqi is None:
2025-07-02 06:41:18.751                         eqi, eqj = i, j
2025-07-02 06:41:18.751                     continue
2025-07-02 06:41:18.752                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.752                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.752                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.752                 # compares by a factor of 3.
2025-07-02 06:41:18.752                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.752                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.752                 # of the computation is cached by cruncher
2025-07-02 06:41:18.752                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.752                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.752                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.752                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.752         if best_ratio < cutoff:
2025-07-02 06:41:18.752             # no non-identical "pretty close" pair
2025-07-02 06:41:18.752             if eqi is None:
2025-07-02 06:41:18.752                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.752                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.752                 return
2025-07-02 06:41:18.752             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.752             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.753         else:
2025-07-02 06:41:18.753             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.753             eqi = None
2025-07-02 06:41:18.753
2025-07-02 06:41:18.753         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.753         # identical
2025-07-02 06:41:18.753
2025-07-02 06:41:18.753         # pump out diffs from before the synch point
2025-07-02 06:41:18.753         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.753
2025-07-02 06:41:18.753         # do intraline marking on the synch pair
2025-07-02 06:41:18.753         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.753         if eqi is None:
2025-07-02 06:41:18.753             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.753             atags = btags = ""
2025-07-02 06:41:18.753             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.753             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.753                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.754                 if tag == 'replace':
2025-07-02 06:41:18.754                     atags += '^' * la
2025-07-02 06:41:18.754                     btags += '^' * lb
2025-07-02 06:41:18.754                 elif tag == 'delete':
2025-07-02 06:41:18.754                     atags += '-' * la
2025-07-02 06:41:18.754                 elif tag == 'insert':
2025-07-02 06:41:18.754                     btags += '+' * lb
2025-07-02 06:41:18.754                 elif tag == 'equal':
2025-07-02 06:41:18.754                     atags += ' ' * la
2025-07-02 06:41:18.754                     btags += ' ' * lb
2025-07-02 06:41:18.754                 else:
2025-07-02 06:41:18.754                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.754             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.754         else:
2025-07-02 06:41:18.754             # the synch pair is identical
2025-07-02 06:41:18.754             yield '  ' + aelt
2025-07-02 06:41:18.754
2025-07-02 06:41:18.754         # pump out diffs from after the synch point
2025-07-02 06:41:18.754 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.755
2025-07-02 06:41:18.755 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.755 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.755
2025-07-02 06:41:18.755 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.755 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.755 alo = 453, ahi = 1101
2025-07-02 06:41:18.755 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.755 blo = 453, bhi = 1101
2025-07-02 06:41:18.755
2025-07-02 06:41:18.755     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.755         g = []
2025-07-02 06:41:18.755         if alo < ahi:
2025-07-02 06:41:18.755             if blo < bhi:
2025-07-02 06:41:18.755                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.755             else:
2025-07-02 06:41:18.755                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.755         elif blo < bhi:
2025-07-02 06:41:18.755             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.756
2025-07-02 06:41:18.756 >       yield from g
2025-07-02 06:41:18.756
2025-07-02 06:41:18.756 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.756 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.756
2025-07-02 06:41:18.756 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.756 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.756 alo = 453, ahi = 1101
2025-07-02 06:41:18.756 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.756 blo = 453, bhi = 1101
2025-07-02 06:41:18.756
2025-07-02 06:41:18.756     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.756         r"""
2025-07-02 06:41:18.756         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.756         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.756         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.756         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.756
2025-07-02 06:41:18.757         Example:
2025-07-02 06:41:18.757
2025-07-02 06:41:18.757         >>> d = Differ()
2025-07-02 06:41:18.757         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.757         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.757         >>> print(''.join(results), end="")
2025-07-02 06:41:18.757         - abcDefghiJkl
2025-07-02 06:41:18.757         + abcdefGhijkl
2025-07-02 06:41:18.757         """
2025-07-02 06:41:18.757
2025-07-02 06:41:18.757         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.757         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.757         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.757         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.757         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.757
2025-07-02 06:41:18.757         # search for the pair that matches best without being identical
2025-07-02 06:41:18.757         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.758         # on junk -- unless we have to)
2025-07-02 06:41:18.758         for j in range(blo, bhi):
2025-07-02 06:41:18.758             bj = b[j]
2025-07-02 06:41:18.758             cruncher.set_seq2(bj)
2025-07-02 06:41:18.758             for i in range(alo, ahi):
2025-07-02 06:41:18.758                 ai = a[i]
2025-07-02 06:41:18.758                 if ai == bj:
2025-07-02 06:41:18.758                     if eqi is None:
2025-07-02 06:41:18.758                         eqi, eqj = i, j
2025-07-02 06:41:18.758                     continue
2025-07-02 06:41:18.758                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.758                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.758                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.758                 # compares by a factor of 3.
2025-07-02 06:41:18.758                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.758                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.758                 # of the computation is cached by cruncher
2025-07-02 06:41:18.758                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.758                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.759                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.759                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.759         if best_ratio < cutoff:
2025-07-02 06:41:18.759             # no non-identical "pretty close" pair
2025-07-02 06:41:18.759             if eqi is None:
2025-07-02 06:41:18.759                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.759                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.759                 return
2025-07-02 06:41:18.759             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.759             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.759         else:
2025-07-02 06:41:18.759             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.759             eqi = None
2025-07-02 06:41:18.759
2025-07-02 06:41:18.759         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.759         # identical
2025-07-02 06:41:18.759
2025-07-02 06:41:18.759         # pump out diffs from before the synch point
2025-07-02 06:41:18.759         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.760
2025-07-02 06:41:18.760         # do intraline marking on the synch pair
2025-07-02 06:41:18.760         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.760         if eqi is None:
2025-07-02 06:41:18.760             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.760             atags = btags = ""
2025-07-02 06:41:18.760             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.760             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.760                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.760                 if tag == 'replace':
2025-07-02 06:41:18.760                     atags += '^' * la
2025-07-02 06:41:18.760                     btags += '^' * lb
2025-07-02 06:41:18.760                 elif tag == 'delete':
2025-07-02 06:41:18.760                     atags += '-' * la
2025-07-02 06:41:18.760                 elif tag == 'insert':
2025-07-02 06:41:18.760                     btags += '+' * lb
2025-07-02 06:41:18.760                 elif tag == 'equal':
2025-07-02 06:41:18.760                     atags += ' ' * la
2025-07-02 06:41:18.761                     btags += ' ' * lb
2025-07-02 06:41:18.761                 else:
2025-07-02 06:41:18.761                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.761             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.761         else:
2025-07-02 06:41:18.761             # the synch pair is identical
2025-07-02 06:41:18.761             yield '  ' + aelt
2025-07-02 06:41:18.761
2025-07-02 06:41:18.761         # pump out diffs from after the synch point
2025-07-02 06:41:18.761 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.761
2025-07-02 06:41:18.761 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.761 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.761
2025-07-02 06:41:18.761 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.761 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.761 alo = 454, ahi = 1101
2025-07-02 06:41:18.761 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.761 blo = 454, bhi = 1101
2025-07-02 06:41:18.762
2025-07-02 06:41:18.762     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.762         g = []
2025-07-02 06:41:18.762         if alo < ahi:
2025-07-02 06:41:18.762             if blo < bhi:
2025-07-02 06:41:18.762                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.762             else:
2025-07-02 06:41:18.762                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.762         elif blo < bhi:
2025-07-02 06:41:18.762             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.762
2025-07-02 06:41:18.762 >       yield from g
2025-07-02 06:41:18.762
2025-07-02 06:41:18.762 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.762 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.762
2025-07-02 06:41:18.762 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.762 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.762 alo = 454, ahi = 1101
2025-07-02 06:41:18.763 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.763 blo = 454, bhi = 1101
2025-07-02 06:41:18.763
2025-07-02 06:41:18.763     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.763         r"""
2025-07-02 06:41:18.763         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.763         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.763         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.763         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.763
2025-07-02 06:41:18.763         Example:
2025-07-02 06:41:18.763
2025-07-02 06:41:18.763         >>> d = Differ()
2025-07-02 06:41:18.763         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.763         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.763         >>> print(''.join(results), end="")
2025-07-02 06:41:18.763         - abcDefghiJkl
2025-07-02 06:41:18.763         + abcdefGhijkl
2025-07-02 06:41:18.764         """
2025-07-02 06:41:18.764
2025-07-02 06:41:18.764         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.764         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.764         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.764         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.764         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.764
2025-07-02 06:41:18.764         # search for the pair that matches best without being identical
2025-07-02 06:41:18.764         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.764         # on junk -- unless we have to)
2025-07-02 06:41:18.764         for j in range(blo, bhi):
2025-07-02 06:41:18.764             bj = b[j]
2025-07-02 06:41:18.764             cruncher.set_seq2(bj)
2025-07-02 06:41:18.764             for i in range(alo, ahi):
2025-07-02 06:41:18.764                 ai = a[i]
2025-07-02 06:41:18.764                 if ai == bj:
2025-07-02 06:41:18.764                     if eqi is None:
2025-07-02 06:41:18.764                         eqi, eqj = i, j
2025-07-02 06:41:18.765                     continue
2025-07-02 06:41:18.765                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.765                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.765                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.765                 # compares by a factor of 3.
2025-07-02 06:41:18.765                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.765                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.765                 # of the computation is cached by cruncher
2025-07-02 06:41:18.765                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.765                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.765                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.765                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.765         if best_ratio < cutoff:
2025-07-02 06:41:18.765             # no non-identical "pretty close" pair
2025-07-02 06:41:18.765             if eqi is None:
2025-07-02 06:41:18.765                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.765                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.765                 return
2025-07-02 06:41:18.765             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.766             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.766         else:
2025-07-02 06:41:18.766             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.766             eqi = None
2025-07-02 06:41:18.766
2025-07-02 06:41:18.766         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.766         # identical
2025-07-02 06:41:18.766
2025-07-02 06:41:18.766         # pump out diffs from before the synch point
2025-07-02 06:41:18.766         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.766
2025-07-02 06:41:18.766         # do intraline marking on the synch pair
2025-07-02 06:41:18.766         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.766         if eqi is None:
2025-07-02 06:41:18.766             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.766             atags = btags = ""
2025-07-02 06:41:18.766             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.766             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.766                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.767                 if tag == 'replace':
2025-07-02 06:41:18.767                     atags += '^' * la
2025-07-02 06:41:18.767                     btags += '^' * lb
2025-07-02 06:41:18.767                 elif tag == 'delete':
2025-07-02 06:41:18.767                     atags += '-' * la
2025-07-02 06:41:18.767                 elif tag == 'insert':
2025-07-02 06:41:18.767                     btags += '+' * lb
2025-07-02 06:41:18.767                 elif tag == 'equal':
2025-07-02 06:41:18.767                     atags += ' ' * la
2025-07-02 06:41:18.767                     btags += ' ' * lb
2025-07-02 06:41:18.767                 else:
2025-07-02 06:41:18.767                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.767             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.767         else:
2025-07-02 06:41:18.767             # the synch pair is identical
2025-07-02 06:41:18.767             yield '  ' + aelt
2025-07-02 06:41:18.767
2025-07-02 06:41:18.767         # pump out diffs from after the synch point
2025-07-02 06:41:18.767 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.767
2025-07-02 06:41:18.768 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.768 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.768
2025-07-02 06:41:18.768 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.768 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.768 alo = 455, ahi = 1101
2025-07-02 06:41:18.768 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.768 blo = 455, bhi = 1101
2025-07-02 06:41:18.768
2025-07-02 06:41:18.768     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.768         g = []
2025-07-02 06:41:18.768         if alo < ahi:
2025-07-02 06:41:18.768             if blo < bhi:
2025-07-02 06:41:18.768                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.768             else:
2025-07-02 06:41:18.768                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.768         elif blo < bhi:
2025-07-02 06:41:18.768             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.768
2025-07-02 06:41:18.769 >       yield from g
2025-07-02 06:41:18.769
2025-07-02 06:41:18.769 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.769 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.769
2025-07-02 06:41:18.769 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.769 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.769 alo = 455, ahi = 1101
2025-07-02 06:41:18.769 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.769 blo = 455, bhi = 1101
2025-07-02 06:41:18.769
2025-07-02 06:41:18.769     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.769         r"""
2025-07-02 06:41:18.769         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.769         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.769         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.769         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.769
2025-07-02 06:41:18.770         Example:
2025-07-02 06:41:18.770
2025-07-02 06:41:18.770         >>> d = Differ()
2025-07-02 06:41:18.770         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.770         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.770         >>> print(''.join(results), end="")
2025-07-02 06:41:18.770         - abcDefghiJkl
2025-07-02 06:41:18.770         + abcdefGhijkl
2025-07-02 06:41:18.770         """
2025-07-02 06:41:18.770
2025-07-02 06:41:18.770         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.770         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.770         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.770         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.770         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.770
2025-07-02 06:41:18.770         # search for the pair that matches best without being identical
2025-07-02 06:41:18.771         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.771         # on junk -- unless we have to)
2025-07-02 06:41:18.771         for j in range(blo, bhi):
2025-07-02 06:41:18.771             bj = b[j]
2025-07-02 06:41:18.771             cruncher.set_seq2(bj)
2025-07-02 06:41:18.771             for i in range(alo, ahi):
2025-07-02 06:41:18.771                 ai = a[i]
2025-07-02 06:41:18.771                 if ai == bj:
2025-07-02 06:41:18.771                     if eqi is None:
2025-07-02 06:41:18.771                         eqi, eqj = i, j
2025-07-02 06:41:18.771                     continue
2025-07-02 06:41:18.771                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.771                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.771                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.771                 # compares by a factor of 3.
2025-07-02 06:41:18.771                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.771                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.771                 # of the computation is cached by cruncher
2025-07-02 06:41:18.771                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.771                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.772                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.772                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.772         if best_ratio < cutoff:
2025-07-02 06:41:18.772             # no non-identical "pretty close" pair
2025-07-02 06:41:18.772             if eqi is None:
2025-07-02 06:41:18.772                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.772                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.772                 return
2025-07-02 06:41:18.772             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.772             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.772         else:
2025-07-02 06:41:18.772             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.772             eqi = None
2025-07-02 06:41:18.772
2025-07-02 06:41:18.772         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.772         # identical
2025-07-02 06:41:18.772
2025-07-02 06:41:18.772         # pump out diffs from before the synch point
2025-07-02 06:41:18.772         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.773
2025-07-02 06:41:18.773         # do intraline marking on the synch pair
2025-07-02 06:41:18.773         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.773         if eqi is None:
2025-07-02 06:41:18.773             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.773             atags = btags = ""
2025-07-02 06:41:18.773             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.773             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.773                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.773                 if tag == 'replace':
2025-07-02 06:41:18.773                     atags += '^' * la
2025-07-02 06:41:18.773                     btags += '^' * lb
2025-07-02 06:41:18.773                 elif tag == 'delete':
2025-07-02 06:41:18.773                     atags += '-' * la
2025-07-02 06:41:18.773                 elif tag == 'insert':
2025-07-02 06:41:18.773                     btags += '+' * lb
2025-07-02 06:41:18.773                 elif tag == 'equal':
2025-07-02 06:41:18.773                     atags += ' ' * la
2025-07-02 06:41:18.773                     btags += ' ' * lb
2025-07-02 06:41:18.773                 else:
2025-07-02 06:41:18.774                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.774             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.774         else:
2025-07-02 06:41:18.774             # the synch pair is identical
2025-07-02 06:41:18.774             yield '  ' + aelt
2025-07-02 06:41:18.774
2025-07-02 06:41:18.774         # pump out diffs from after the synch point
2025-07-02 06:41:18.774 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.774
2025-07-02 06:41:18.774 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.774 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.774
2025-07-02 06:41:18.774 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.774 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.774 alo = 456, ahi = 1101
2025-07-02 06:41:18.774 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.774 blo = 456, bhi = 1101
2025-07-02 06:41:18.774
2025-07-02 06:41:18.774     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.775         g = []
2025-07-02 06:41:18.775         if alo < ahi:
2025-07-02 06:41:18.775             if blo < bhi:
2025-07-02 06:41:18.775                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.775             else:
2025-07-02 06:41:18.775                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.775         elif blo < bhi:
2025-07-02 06:41:18.775             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.775
2025-07-02 06:41:18.775 >       yield from g
2025-07-02 06:41:18.775
2025-07-02 06:41:18.775 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.775 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.775
2025-07-02 06:41:18.775 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.775 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.775 alo = 456, ahi = 1101
2025-07-02 06:41:18.775 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.775 blo = 456, bhi = 1101
2025-07-02 06:41:18.776
2025-07-02 06:41:18.776     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.776         r"""
2025-07-02 06:41:18.776         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.776         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.776         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.776         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.776
2025-07-02 06:41:18.776         Example:
2025-07-02 06:41:18.776
2025-07-02 06:41:18.776         >>> d = Differ()
2025-07-02 06:41:18.776         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.776         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.776         >>> print(''.join(results), end="")
2025-07-02 06:41:18.776         - abcDefghiJkl
2025-07-02 06:41:18.776         + abcdefGhijkl
2025-07-02 06:41:18.776         """
2025-07-02 06:41:18.776
2025-07-02 06:41:18.777         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.777         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.777         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.777         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.777         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.777
2025-07-02 06:41:18.777         # search for the pair that matches best without being identical
2025-07-02 06:41:18.777         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.777         # on junk -- unless we have to)
2025-07-02 06:41:18.777         for j in range(blo, bhi):
2025-07-02 06:41:18.777             bj = b[j]
2025-07-02 06:41:18.777             cruncher.set_seq2(bj)
2025-07-02 06:41:18.777             for i in range(alo, ahi):
2025-07-02 06:41:18.777                 ai = a[i]
2025-07-02 06:41:18.777                 if ai == bj:
2025-07-02 06:41:18.777                     if eqi is None:
2025-07-02 06:41:18.777                         eqi, eqj = i, j
2025-07-02 06:41:18.777                     continue
2025-07-02 06:41:18.778                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.778                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.778                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.778                 # compares by a factor of 3.
2025-07-02 06:41:18.778                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.778                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.778                 # of the computation is cached by cruncher
2025-07-02 06:41:18.778                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.778                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.778                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.778                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.778         if best_ratio < cutoff:
2025-07-02 06:41:18.778             # no non-identical "pretty close" pair
2025-07-02 06:41:18.778             if eqi is None:
2025-07-02 06:41:18.778                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.778                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.778                 return
2025-07-02 06:41:18.778             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.778             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.779         else:
2025-07-02 06:41:18.779             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.779             eqi = None
2025-07-02 06:41:18.779
2025-07-02 06:41:18.779         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.779         # identical
2025-07-02 06:41:18.779
2025-07-02 06:41:18.779         # pump out diffs from before the synch point
2025-07-02 06:41:18.779         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.779
2025-07-02 06:41:18.779         # do intraline marking on the synch pair
2025-07-02 06:41:18.779         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.779         if eqi is None:
2025-07-02 06:41:18.779             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.779             atags = btags = ""
2025-07-02 06:41:18.779             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.779             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.779                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.779                 if tag == 'replace':
2025-07-02 06:41:18.779                     atags += '^' * la
2025-07-02 06:41:18.780                     btags += '^' * lb
2025-07-02 06:41:18.780                 elif tag == 'delete':
2025-07-02 06:41:18.780                     atags += '-' * la
2025-07-02 06:41:18.780                 elif tag == 'insert':
2025-07-02 06:41:18.780                     btags += '+' * lb
2025-07-02 06:41:18.780                 elif tag == 'equal':
2025-07-02 06:41:18.780                     atags += ' ' * la
2025-07-02 06:41:18.780                     btags += ' ' * lb
2025-07-02 06:41:18.780                 else:
2025-07-02 06:41:18.780                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.780             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.780         else:
2025-07-02 06:41:18.780             # the synch pair is identical
2025-07-02 06:41:18.780             yield '  ' + aelt
2025-07-02 06:41:18.780
2025-07-02 06:41:18.780         # pump out diffs from after the synch point
2025-07-02 06:41:18.780 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.780
2025-07-02 06:41:18.780 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.781 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.781
2025-07-02 06:41:18.781 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.781 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.781 alo = 457, ahi = 1101
2025-07-02 06:41:18.781 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.781 blo = 457, bhi = 1101
2025-07-02 06:41:18.781
2025-07-02 06:41:18.781     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.781         g = []
2025-07-02 06:41:18.781         if alo < ahi:
2025-07-02 06:41:18.781             if blo < bhi:
2025-07-02 06:41:18.781                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.781             else:
2025-07-02 06:41:18.781                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.781         elif blo < bhi:
2025-07-02 06:41:18.781             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.781
2025-07-02 06:41:18.781 >       yield from g
2025-07-02 06:41:18.781
2025-07-02 06:41:18.782 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.782 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.782
2025-07-02 06:41:18.782 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.782 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.782 alo = 457, ahi = 1101
2025-07-02 06:41:18.782 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.782 blo = 457, bhi = 1101
2025-07-02 06:41:18.782
2025-07-02 06:41:18.782     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.782         r"""
2025-07-02 06:41:18.782         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.782         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.782         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.782         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.782
2025-07-02 06:41:18.782         Example:
2025-07-02 06:41:18.782
2025-07-02 06:41:18.782         >>> d = Differ()
2025-07-02 06:41:18.783         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.783         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.783         >>> print(''.join(results), end="")
2025-07-02 06:41:18.783         - abcDefghiJkl
2025-07-02 06:41:18.783         + abcdefGhijkl
2025-07-02 06:41:18.783         """
2025-07-02 06:41:18.783
2025-07-02 06:41:18.783         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.783         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.783         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.783         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.783         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.783
2025-07-02 06:41:18.783         # search for the pair that matches best without being identical
2025-07-02 06:41:18.783         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.783         # on junk -- unless we have to)
2025-07-02 06:41:18.783         for j in range(blo, bhi):
2025-07-02 06:41:18.784             bj = b[j]
2025-07-02 06:41:18.784             cruncher.set_seq2(bj)
2025-07-02 06:41:18.784             for i in range(alo, ahi):
2025-07-02 06:41:18.784                 ai = a[i]
2025-07-02 06:41:18.784                 if ai == bj:
2025-07-02 06:41:18.784                     if eqi is None:
2025-07-02 06:41:18.784                         eqi, eqj = i, j
2025-07-02 06:41:18.784                     continue
2025-07-02 06:41:18.784                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.784                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.784                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.784                 # compares by a factor of 3.
2025-07-02 06:41:18.784                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.784                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.784                 # of the computation is cached by cruncher
2025-07-02 06:41:18.784                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.784                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.784                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.784                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.785         if best_ratio < cutoff:
2025-07-02 06:41:18.785             # no non-identical "pretty close" pair
2025-07-02 06:41:18.785             if eqi is None:
2025-07-02 06:41:18.785                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.785                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.785                 return
2025-07-02 06:41:18.785             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.785             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.785         else:
2025-07-02 06:41:18.785             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.785             eqi = None
2025-07-02 06:41:18.785
2025-07-02 06:41:18.785         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.785         # identical
2025-07-02 06:41:18.785
2025-07-02 06:41:18.785         # pump out diffs from before the synch point
2025-07-02 06:41:18.785         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.785
2025-07-02 06:41:18.785         # do intraline marking on the synch pair
2025-07-02 06:41:18.786         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.786         if eqi is None:
2025-07-02 06:41:18.786             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.786             atags = btags = ""
2025-07-02 06:41:18.786             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.786             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.786                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.786                 if tag == 'replace':
2025-07-02 06:41:18.786                     atags += '^' * la
2025-07-02 06:41:18.786                     btags += '^' * lb
2025-07-02 06:41:18.786                 elif tag == 'delete':
2025-07-02 06:41:18.786                     atags += '-' * la
2025-07-02 06:41:18.786                 elif tag == 'insert':
2025-07-02 06:41:18.786                     btags += '+' * lb
2025-07-02 06:41:18.786                 elif tag == 'equal':
2025-07-02 06:41:18.786                     atags += ' ' * la
2025-07-02 06:41:18.786                     btags += ' ' * lb
2025-07-02 06:41:18.786                 else:
2025-07-02 06:41:18.786                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.786             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.787         else:
2025-07-02 06:41:18.787             # the synch pair is identical
2025-07-02 06:41:18.787             yield '  ' + aelt
2025-07-02 06:41:18.787
2025-07-02 06:41:18.787         # pump out diffs from after the synch point
2025-07-02 06:41:18.787 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.787
2025-07-02 06:41:18.787 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.787 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.787
2025-07-02 06:41:18.787 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.787 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.787 alo = 458, ahi = 1101
2025-07-02 06:41:18.787 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.787 blo = 458, bhi = 1101
2025-07-02 06:41:18.787
2025-07-02 06:41:18.787     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.787         g = []
2025-07-02 06:41:18.788         if alo < ahi:
2025-07-02 06:41:18.788             if blo < bhi:
2025-07-02 06:41:18.788                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.788             else:
2025-07-02 06:41:18.788                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.788         elif blo < bhi:
2025-07-02 06:41:18.788             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.788
2025-07-02 06:41:18.788 >       yield from g
2025-07-02 06:41:18.788
2025-07-02 06:41:18.788 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.788 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.788
2025-07-02 06:41:18.788 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.788 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.788 alo = 458, ahi = 1101
2025-07-02 06:41:18.788 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.788 blo = 458, bhi = 1101
2025-07-02 06:41:18.789
2025-07-02 06:41:18.789     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.789         r"""
2025-07-02 06:41:18.789         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.789         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.789         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.789         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.789
2025-07-02 06:41:18.789         Example:
2025-07-02 06:41:18.789
2025-07-02 06:41:18.789         >>> d = Differ()
2025-07-02 06:41:18.789         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.789         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.789         >>> print(''.join(results), end="")
2025-07-02 06:41:18.789         - abcDefghiJkl
2025-07-02 06:41:18.789         + abcdefGhijkl
2025-07-02 06:41:18.789         """
2025-07-02 06:41:18.789
2025-07-02 06:41:18.790         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.790         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.790         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.790         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.790         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.790
2025-07-02 06:41:18.790         # search for the pair that matches best without being identical
2025-07-02 06:41:18.790         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.790         # on junk -- unless we have to)
2025-07-02 06:41:18.790         for j in range(blo, bhi):
2025-07-02 06:41:18.790             bj = b[j]
2025-07-02 06:41:18.790             cruncher.set_seq2(bj)
2025-07-02 06:41:18.790             for i in range(alo, ahi):
2025-07-02 06:41:18.790                 ai = a[i]
2025-07-02 06:41:18.790                 if ai == bj:
2025-07-02 06:41:18.790                     if eqi is None:
2025-07-02 06:41:18.790                         eqi, eqj = i, j
2025-07-02 06:41:18.790                     continue
2025-07-02 06:41:18.790                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.791                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.791                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.791                 # compares by a factor of 3.
2025-07-02 06:41:18.791                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.791                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.791                 # of the computation is cached by cruncher
2025-07-02 06:41:18.791                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.791                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.791                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.791                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.791         if best_ratio < cutoff:
2025-07-02 06:41:18.791             # no non-identical "pretty close" pair
2025-07-02 06:41:18.791             if eqi is None:
2025-07-02 06:41:18.791                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.791                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.791                 return
2025-07-02 06:41:18.791             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.791             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.791         else:
2025-07-02 06:41:18.791             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.792             eqi = None
2025-07-02 06:41:18.792
2025-07-02 06:41:18.792         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.792         # identical
2025-07-02 06:41:18.792
2025-07-02 06:41:18.792         # pump out diffs from before the synch point
2025-07-02 06:41:18.792         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.792
2025-07-02 06:41:18.792         # do intraline marking on the synch pair
2025-07-02 06:41:18.792         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.792         if eqi is None:
2025-07-02 06:41:18.792             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.792             atags = btags = ""
2025-07-02 06:41:18.792             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.792             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.792                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.792                 if tag == 'replace':
2025-07-02 06:41:18.792                     atags += '^' * la
2025-07-02 06:41:18.792                     btags += '^' * lb
2025-07-02 06:41:18.793                 elif tag == 'delete':
2025-07-02 06:41:18.793                     atags += '-' * la
2025-07-02 06:41:18.793                 elif tag == 'insert':
2025-07-02 06:41:18.793                     btags += '+' * lb
2025-07-02 06:41:18.793                 elif tag == 'equal':
2025-07-02 06:41:18.793                     atags += ' ' * la
2025-07-02 06:41:18.793                     btags += ' ' * lb
2025-07-02 06:41:18.793                 else:
2025-07-02 06:41:18.793                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.793             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.793         else:
2025-07-02 06:41:18.793             # the synch pair is identical
2025-07-02 06:41:18.793             yield '  ' + aelt
2025-07-02 06:41:18.793
2025-07-02 06:41:18.793         # pump out diffs from after the synch point
2025-07-02 06:41:18.793 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.793
2025-07-02 06:41:18.793 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.793 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.793
2025-07-02 06:41:18.794 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.794 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.794 alo = 459, ahi = 1101
2025-07-02 06:41:18.794 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.794 blo = 459, bhi = 1101
2025-07-02 06:41:18.794
2025-07-02 06:41:18.794     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.794         g = []
2025-07-02 06:41:18.794         if alo < ahi:
2025-07-02 06:41:18.794             if blo < bhi:
2025-07-02 06:41:18.794                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.794             else:
2025-07-02 06:41:18.794                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.794         elif blo < bhi:
2025-07-02 06:41:18.794             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.794
2025-07-02 06:41:18.794 >       yield from g
2025-07-02 06:41:18.794
2025-07-02 06:41:18.794 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.795 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.795
2025-07-02 06:41:18.795 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.795 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.795 alo = 459, ahi = 1101
2025-07-02 06:41:18.795 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.795 blo = 459, bhi = 1101
2025-07-02 06:41:18.795
2025-07-02 06:41:18.795     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.795         r"""
2025-07-02 06:41:18.795         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.795         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.795         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.795         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.795
2025-07-02 06:41:18.795         Example:
2025-07-02 06:41:18.795
2025-07-02 06:41:18.795         >>> d = Differ()
2025-07-02 06:41:18.795         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.796         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.796         >>> print(''.join(results), end="")
2025-07-02 06:41:18.796         - abcDefghiJkl
2025-07-02 06:41:18.796         + abcdefGhijkl
2025-07-02 06:41:18.796         """
2025-07-02 06:41:18.796
2025-07-02 06:41:18.796         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.796         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.796         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.796         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.796         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.796
2025-07-02 06:41:18.796         # search for the pair that matches best without being identical
2025-07-02 06:41:18.796         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.796         # on junk -- unless we have to)
2025-07-02 06:41:18.796         for j in range(blo, bhi):
2025-07-02 06:41:18.796             bj = b[j]
2025-07-02 06:41:18.797             cruncher.set_seq2(bj)
2025-07-02 06:41:18.797             for i in range(alo, ahi):
2025-07-02 06:41:18.797                 ai = a[i]
2025-07-02 06:41:18.797                 if ai == bj:
2025-07-02 06:41:18.797                     if eqi is None:
2025-07-02 06:41:18.797                         eqi, eqj = i, j
2025-07-02 06:41:18.797                     continue
2025-07-02 06:41:18.797                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.797                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.797                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.797                 # compares by a factor of 3.
2025-07-02 06:41:18.797                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.797                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.797                 # of the computation is cached by cruncher
2025-07-02 06:41:18.797                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.797                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.797                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.797                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.797         if best_ratio < cutoff:
2025-07-02 06:41:18.797             # no non-identical "pretty close" pair
2025-07-02 06:41:18.798             if eqi is None:
2025-07-02 06:41:18.798                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.798                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.798                 return
2025-07-02 06:41:18.798             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.798             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.798         else:
2025-07-02 06:41:18.798             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.798             eqi = None
2025-07-02 06:41:18.798
2025-07-02 06:41:18.798         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.798         # identical
2025-07-02 06:41:18.798
2025-07-02 06:41:18.798         # pump out diffs from before the synch point
2025-07-02 06:41:18.798         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.798
2025-07-02 06:41:18.798         # do intraline marking on the synch pair
2025-07-02 06:41:18.798         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.798         if eqi is None:
2025-07-02 06:41:18.798             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.799             atags = btags = ""
2025-07-02 06:41:18.799             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.799             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.799                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.799                 if tag == 'replace':
2025-07-02 06:41:18.799                     atags += '^' * la
2025-07-02 06:41:18.799                     btags += '^' * lb
2025-07-02 06:41:18.799                 elif tag == 'delete':
2025-07-02 06:41:18.799                     atags += '-' * la
2025-07-02 06:41:18.799                 elif tag == 'insert':
2025-07-02 06:41:18.799                     btags += '+' * lb
2025-07-02 06:41:18.799                 elif tag == 'equal':
2025-07-02 06:41:18.799                     atags += ' ' * la
2025-07-02 06:41:18.799                     btags += ' ' * lb
2025-07-02 06:41:18.799                 else:
2025-07-02 06:41:18.799                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.799             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.799         else:
2025-07-02 06:41:18.800             # the synch pair is identical
2025-07-02 06:41:18.800             yield '  ' + aelt
2025-07-02 06:41:18.800
2025-07-02 06:41:18.800         # pump out diffs from after the synch point
2025-07-02 06:41:18.800 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.800
2025-07-02 06:41:18.800 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.800 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.800
2025-07-02 06:41:18.800 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.800 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.800 alo = 460, ahi = 1101
2025-07-02 06:41:18.800 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.800 blo = 460, bhi = 1101
2025-07-02 06:41:18.800
2025-07-02 06:41:18.800     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.800         g = []
2025-07-02 06:41:18.800         if alo < ahi:
2025-07-02 06:41:18.800             if blo < bhi:
2025-07-02 06:41:18.801                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.801             else:
2025-07-02 06:41:18.801                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.801         elif blo < bhi:
2025-07-02 06:41:18.801             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.801
2025-07-02 06:41:18.801 >       yield from g
2025-07-02 06:41:18.801
2025-07-02 06:41:18.801 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.801 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.801
2025-07-02 06:41:18.801 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.801 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.801 alo = 460, ahi = 1101
2025-07-02 06:41:18.801 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.801 blo = 460, bhi = 1101
2025-07-02 06:41:18.801
2025-07-02 06:41:18.801     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.801         r"""
2025-07-02 06:41:18.801         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.801         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.802         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.802         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.802
2025-07-02 06:41:18.802         Example:
2025-07-02 06:41:18.802
2025-07-02 06:41:18.802         >>> d = Differ()
2025-07-02 06:41:18.802         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.802         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.802         >>> print(''.join(results), end="")
2025-07-02 06:41:18.802         - abcDefghiJkl
2025-07-02 06:41:18.802         + abcdefGhijkl
2025-07-02 06:41:18.802         """
2025-07-02 06:41:18.802
2025-07-02 06:41:18.802         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.802         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.802         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.802         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.802         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.803
2025-07-02 06:41:18.803         # search for the pair that matches best without being identical
2025-07-02 06:41:18.803         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.803         # on junk -- unless we have to)
2025-07-02 06:41:18.803         for j in range(blo, bhi):
2025-07-02 06:41:18.803             bj = b[j]
2025-07-02 06:41:18.803             cruncher.set_seq2(bj)
2025-07-02 06:41:18.803             for i in range(alo, ahi):
2025-07-02 06:41:18.803                 ai = a[i]
2025-07-02 06:41:18.803                 if ai == bj:
2025-07-02 06:41:18.803                     if eqi is None:
2025-07-02 06:41:18.803                         eqi, eqj = i, j
2025-07-02 06:41:18.803                     continue
2025-07-02 06:41:18.803                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.803                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.803                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.803                 # compares by a factor of 3.
2025-07-02 06:41:18.803                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.803                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.803                 # of the computation is cached by cruncher
2025-07-02 06:41:18.804                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.804                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.804                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.804                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.804         if best_ratio < cutoff:
2025-07-02 06:41:18.804             # no non-identical "pretty close" pair
2025-07-02 06:41:18.804             if eqi is None:
2025-07-02 06:41:18.804                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.804                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.804                 return
2025-07-02 06:41:18.804             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.804             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.804         else:
2025-07-02 06:41:18.804             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.804             eqi = None
2025-07-02 06:41:18.804
2025-07-02 06:41:18.804         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.804         # identical
2025-07-02 06:41:18.804
2025-07-02 06:41:18.804         # pump out diffs from before the synch point
2025-07-02 06:41:18.804         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.805
2025-07-02 06:41:18.805         # do intraline marking on the synch pair
2025-07-02 06:41:18.805         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.805         if eqi is None:
2025-07-02 06:41:18.805             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.805             atags = btags = ""
2025-07-02 06:41:18.805             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.805             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.805                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.805                 if tag == 'replace':
2025-07-02 06:41:18.805                     atags += '^' * la
2025-07-02 06:41:18.805                     btags += '^' * lb
2025-07-02 06:41:18.805                 elif tag == 'delete':
2025-07-02 06:41:18.805                     atags += '-' * la
2025-07-02 06:41:18.805                 elif tag == 'insert':
2025-07-02 06:41:18.805                     btags += '+' * lb
2025-07-02 06:41:18.806                 elif tag == 'equal':
2025-07-02 06:41:18.806                     atags += ' ' * la
2025-07-02 06:41:18.806                     btags += ' ' * lb
2025-07-02 06:41:18.806                 else:
2025-07-02 06:41:18.806                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.806             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.806         else:
2025-07-02 06:41:18.806             # the synch pair is identical
2025-07-02 06:41:18.806             yield '  ' + aelt
2025-07-02 06:41:18.806
2025-07-02 06:41:18.806         # pump out diffs from after the synch point
2025-07-02 06:41:18.806 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.806
2025-07-02 06:41:18.806 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.806 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.806
2025-07-02 06:41:18.806 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.806 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.806 alo = 461, ahi = 1101
2025-07-02 06:41:18.807 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.807 blo = 461, bhi = 1101
2025-07-02 06:41:18.807
2025-07-02 06:41:18.807     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.807         g = []
2025-07-02 06:41:18.807         if alo < ahi:
2025-07-02 06:41:18.807             if blo < bhi:
2025-07-02 06:41:18.807                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.807             else:
2025-07-02 06:41:18.807                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.807         elif blo < bhi:
2025-07-02 06:41:18.807             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.807
2025-07-02 06:41:18.807 >       yield from g
2025-07-02 06:41:18.807
2025-07-02 06:41:18.807 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.807 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.807
2025-07-02 06:41:18.807 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.807 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.808 alo = 461, ahi = 1101
2025-07-02 06:41:18.808 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.808 blo = 461, bhi = 1101
2025-07-02 06:41:18.808
2025-07-02 06:41:18.808     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.808         r"""
2025-07-02 06:41:18.808         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.808         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.808         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.808         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.808
2025-07-02 06:41:18.808         Example:
2025-07-02 06:41:18.808
2025-07-02 06:41:18.808         >>> d = Differ()
2025-07-02 06:41:18.808         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.808         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.808         >>> print(''.join(results), end="")
2025-07-02 06:41:18.808         - abcDefghiJkl
2025-07-02 06:41:18.808         + abcdefGhijkl
2025-07-02 06:41:18.809         """
2025-07-02 06:41:18.809
2025-07-02 06:41:18.809         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.809         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.809         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.809         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.809         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.809
2025-07-02 06:41:18.809         # search for the pair that matches best without being identical
2025-07-02 06:41:18.809         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.809         # on junk -- unless we have to)
2025-07-02 06:41:18.809         for j in range(blo, bhi):
2025-07-02 06:41:18.809             bj = b[j]
2025-07-02 06:41:18.809             cruncher.set_seq2(bj)
2025-07-02 06:41:18.809             for i in range(alo, ahi):
2025-07-02 06:41:18.809                 ai = a[i]
2025-07-02 06:41:18.809                 if ai == bj:
2025-07-02 06:41:18.809                     if eqi is None:
2025-07-02 06:41:18.809                         eqi, eqj = i, j
2025-07-02 06:41:18.810                     continue
2025-07-02 06:41:18.810                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.810                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.810                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.810                 # compares by a factor of 3.
2025-07-02 06:41:18.810                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.810                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.810                 # of the computation is cached by cruncher
2025-07-02 06:41:18.810                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.810                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.810                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.810                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.810         if best_ratio < cutoff:
2025-07-02 06:41:18.810             # no non-identical "pretty close" pair
2025-07-02 06:41:18.810             if eqi is None:
2025-07-02 06:41:18.810                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.810                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.810                 return
2025-07-02 06:41:18.810             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.810             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.811         else:
2025-07-02 06:41:18.811             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.811             eqi = None
2025-07-02 06:41:18.811
2025-07-02 06:41:18.811         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.811         # identical
2025-07-02 06:41:18.811
2025-07-02 06:41:18.811         # pump out diffs from before the synch point
2025-07-02 06:41:18.811         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.811
2025-07-02 06:41:18.811         # do intraline marking on the synch pair
2025-07-02 06:41:18.811         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.811         if eqi is None:
2025-07-02 06:41:18.811             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.811             atags = btags = ""
2025-07-02 06:41:18.811             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.811             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.811                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.811                 if tag == 'replace':
2025-07-02 06:41:18.811                     atags += '^' * la
2025-07-02 06:41:18.811                     btags += '^' * lb
2025-07-02 06:41:18.812                 elif tag == 'delete':
2025-07-02 06:41:18.812                     atags += '-' * la
2025-07-02 06:41:18.812                 elif tag == 'insert':
2025-07-02 06:41:18.812                     btags += '+' * lb
2025-07-02 06:41:18.812                 elif tag == 'equal':
2025-07-02 06:41:18.812                     atags += ' ' * la
2025-07-02 06:41:18.812                     btags += ' ' * lb
2025-07-02 06:41:18.812                 else:
2025-07-02 06:41:18.812                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.812             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.812         else:
2025-07-02 06:41:18.812             # the synch pair is identical
2025-07-02 06:41:18.812             yield '  ' + aelt
2025-07-02 06:41:18.812
2025-07-02 06:41:18.812         # pump out diffs from after the synch point
2025-07-02 06:41:18.812 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.812
2025-07-02 06:41:18.812 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.812 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.812
2025-07-02 06:41:18.813 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.813 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.813 alo = 462, ahi = 1101
2025-07-02 06:41:18.813 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.813 blo = 462, bhi = 1101
2025-07-02 06:41:18.813
2025-07-02 06:41:18.813     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.813         g = []
2025-07-02 06:41:18.813         if alo < ahi:
2025-07-02 06:41:18.813             if blo < bhi:
2025-07-02 06:41:18.813                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.813             else:
2025-07-02 06:41:18.813                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.813         elif blo < bhi:
2025-07-02 06:41:18.813             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.813
2025-07-02 06:41:18.813 >       yield from g
2025-07-02 06:41:18.813
2025-07-02 06:41:18.813 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.813 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.814
2025-07-02 06:41:18.814 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.814 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.814 alo = 462, ahi = 1101
2025-07-02 06:41:18.814 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.814 blo = 462, bhi = 1101
2025-07-02 06:41:18.814
2025-07-02 06:41:18.814     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.814         r"""
2025-07-02 06:41:18.814         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.814         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.814         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.814         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.814
2025-07-02 06:41:18.814         Example:
2025-07-02 06:41:18.814
2025-07-02 06:41:18.814         >>> d = Differ()
2025-07-02 06:41:18.814         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.814         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.815         >>> print(''.join(results), end="")
2025-07-02 06:41:18.815         - abcDefghiJkl
2025-07-02 06:41:18.815         + abcdefGhijkl
2025-07-02 06:41:18.815         """
2025-07-02 06:41:18.815
2025-07-02 06:41:18.815         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.815         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.815         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.815         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.815         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.815
2025-07-02 06:41:18.815         # search for the pair that matches best without being identical
2025-07-02 06:41:18.815         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.815         # on junk -- unless we have to)
2025-07-02 06:41:18.815         for j in range(blo, bhi):
2025-07-02 06:41:18.815             bj = b[j]
2025-07-02 06:41:18.815             cruncher.set_seq2(bj)
2025-07-02 06:41:18.816             for i in range(alo, ahi):
2025-07-02 06:41:18.816                 ai = a[i]
2025-07-02 06:41:18.816                 if ai == bj:
2025-07-02 06:41:18.816                     if eqi is None:
2025-07-02 06:41:18.816                         eqi, eqj = i, j
2025-07-02 06:41:18.816                     continue
2025-07-02 06:41:18.816                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.816                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.816                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.816                 # compares by a factor of 3.
2025-07-02 06:41:18.816                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.816                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.816                 # of the computation is cached by cruncher
2025-07-02 06:41:18.816                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.816                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.816                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.816                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.816         if best_ratio < cutoff:
2025-07-02 06:41:18.816             # no non-identical "pretty close" pair
2025-07-02 06:41:18.817             if eqi is None:
2025-07-02 06:41:18.817                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.817                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.817                 return
2025-07-02 06:41:18.817             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.817             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.817         else:
2025-07-02 06:41:18.817             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.817             eqi = None
2025-07-02 06:41:18.817
2025-07-02 06:41:18.817         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.817         # identical
2025-07-02 06:41:18.817
2025-07-02 06:41:18.817         # pump out diffs from before the synch point
2025-07-02 06:41:18.817         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.817
2025-07-02 06:41:18.817         # do intraline marking on the synch pair
2025-07-02 06:41:18.817         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.817         if eqi is None:
2025-07-02 06:41:18.818             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.818             atags = btags = ""
2025-07-02 06:41:18.818             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.818             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.818                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.818                 if tag == 'replace':
2025-07-02 06:41:18.818                     atags += '^' * la
2025-07-02 06:41:18.818                     btags += '^' * lb
2025-07-02 06:41:18.818                 elif tag == 'delete':
2025-07-02 06:41:18.818                     atags += '-' * la
2025-07-02 06:41:18.818                 elif tag == 'insert':
2025-07-02 06:41:18.818                     btags += '+' * lb
2025-07-02 06:41:18.818                 elif tag == 'equal':
2025-07-02 06:41:18.818                     atags += ' ' * la
2025-07-02 06:41:18.818                     btags += ' ' * lb
2025-07-02 06:41:18.818                 else:
2025-07-02 06:41:18.818                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.818             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.818         else:
2025-07-02 06:41:18.818             # the synch pair is identical
2025-07-02 06:41:18.819             yield '  ' + aelt
2025-07-02 06:41:18.819
2025-07-02 06:41:18.819         # pump out diffs from after the synch point
2025-07-02 06:41:18.819 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.819
2025-07-02 06:41:18.819 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.819 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.819
2025-07-02 06:41:18.819 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.819 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.819 alo = 463, ahi = 1101
2025-07-02 06:41:18.819 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.819 blo = 463, bhi = 1101
2025-07-02 06:41:18.819
2025-07-02 06:41:18.819     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.819         g = []
2025-07-02 06:41:18.819         if alo < ahi:
2025-07-02 06:41:18.819             if blo < bhi:
2025-07-02 06:41:18.819                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.819             else:
2025-07-02 06:41:18.820                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.820         elif blo < bhi:
2025-07-02 06:41:18.820             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.820
2025-07-02 06:41:18.820 >       yield from g
2025-07-02 06:41:18.820
2025-07-02 06:41:18.820 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.820 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.820
2025-07-02 06:41:18.820 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.820 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.820 alo = 463, ahi = 1101
2025-07-02 06:41:18.820 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.820 blo = 463, bhi = 1101
2025-07-02 06:41:18.820
2025-07-02 06:41:18.820     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.820         r"""
2025-07-02 06:41:18.820         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.820         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.820         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.821         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.821
2025-07-02 06:41:18.821         Example:
2025-07-02 06:41:18.821
2025-07-02 06:41:18.821         >>> d = Differ()
2025-07-02 06:41:18.821         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.821         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.821         >>> print(''.join(results), end="")
2025-07-02 06:41:18.821         - abcDefghiJkl
2025-07-02 06:41:18.821         + abcdefGhijkl
2025-07-02 06:41:18.821         """
2025-07-02 06:41:18.821
2025-07-02 06:41:18.821         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.821         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.821         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.821         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.821         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.821
2025-07-02 06:41:18.821         # search for the pair that matches best without being identical
2025-07-02 06:41:18.822         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.822         # on junk -- unless we have to)
2025-07-02 06:41:18.822         for j in range(blo, bhi):
2025-07-02 06:41:18.822             bj = b[j]
2025-07-02 06:41:18.822             cruncher.set_seq2(bj)
2025-07-02 06:41:18.822             for i in range(alo, ahi):
2025-07-02 06:41:18.822                 ai = a[i]
2025-07-02 06:41:18.822                 if ai == bj:
2025-07-02 06:41:18.822                     if eqi is None:
2025-07-02 06:41:18.822                         eqi, eqj = i, j
2025-07-02 06:41:18.822                     continue
2025-07-02 06:41:18.822                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.822                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.822                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.822                 # compares by a factor of 3.
2025-07-02 06:41:18.822                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.822                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.822                 # of the computation is cached by cruncher
2025-07-02 06:41:18.823                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.823                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.823                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.823                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.823         if best_ratio < cutoff:
2025-07-02 06:41:18.823             # no non-identical "pretty close" pair
2025-07-02 06:41:18.823             if eqi is None:
2025-07-02 06:41:18.823                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.823                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.823                 return
2025-07-02 06:41:18.823             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.823             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.823         else:
2025-07-02 06:41:18.823             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.823             eqi = None
2025-07-02 06:41:18.823
2025-07-02 06:41:18.823         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.823         # identical
2025-07-02 06:41:18.823
2025-07-02 06:41:18.824         # pump out diffs from before the synch point
2025-07-02 06:41:18.824         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.824
2025-07-02 06:41:18.824         # do intraline marking on the synch pair
2025-07-02 06:41:18.824         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.824         if eqi is None:
2025-07-02 06:41:18.824             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.824             atags = btags = ""
2025-07-02 06:41:18.824             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.824             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.824                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.824                 if tag == 'replace':
2025-07-02 06:41:18.824                     atags += '^' * la
2025-07-02 06:41:18.824                     btags += '^' * lb
2025-07-02 06:41:18.824                 elif tag == 'delete':
2025-07-02 06:41:18.824                     atags += '-' * la
2025-07-02 06:41:18.824                 elif tag == 'insert':
2025-07-02 06:41:18.824                     btags += '+' * lb
2025-07-02 06:41:18.824                 elif tag == 'equal':
2025-07-02 06:41:18.824                     atags += ' ' * la
2025-07-02 06:41:18.825                     btags += ' ' * lb
2025-07-02 06:41:18.825                 else:
2025-07-02 06:41:18.825                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.825             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.825         else:
2025-07-02 06:41:18.825             # the synch pair is identical
2025-07-02 06:41:18.825             yield '  ' + aelt
2025-07-02 06:41:18.825
2025-07-02 06:41:18.825         # pump out diffs from after the synch point
2025-07-02 06:41:18.825 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.825
2025-07-02 06:41:18.825 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.825 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.825
2025-07-02 06:41:18.825 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.825 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.825 alo = 466, ahi = 1101
2025-07-02 06:41:18.825 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.825 blo = 466, bhi = 1101
2025-07-02 06:41:18.825
2025-07-02 06:41:18.826     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.826         g = []
2025-07-02 06:41:18.826         if alo < ahi:
2025-07-02 06:41:18.826             if blo < bhi:
2025-07-02 06:41:18.826                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.826             else:
2025-07-02 06:41:18.826                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.826         elif blo < bhi:
2025-07-02 06:41:18.826             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.826
2025-07-02 06:41:18.826 >       yield from g
2025-07-02 06:41:18.826
2025-07-02 06:41:18.826 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.826 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.826
2025-07-02 06:41:18.826 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.826 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.826 alo = 466, ahi = 1101
2025-07-02 06:41:18.826 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.826 blo = 466, bhi = 1101
2025-07-02 06:41:18.827
2025-07-02 06:41:18.827     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.827         r"""
2025-07-02 06:41:18.827         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.827         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.827         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.827         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.827
2025-07-02 06:41:18.827         Example:
2025-07-02 06:41:18.827
2025-07-02 06:41:18.827         >>> d = Differ()
2025-07-02 06:41:18.827         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.827         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.827         >>> print(''.join(results), end="")
2025-07-02 06:41:18.827         - abcDefghiJkl
2025-07-02 06:41:18.827         + abcdefGhijkl
2025-07-02 06:41:18.827         """
2025-07-02 06:41:18.827
2025-07-02 06:41:18.828         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.828         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.828         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.828         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.828         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.828
2025-07-02 06:41:18.828         # search for the pair that matches best without being identical
2025-07-02 06:41:18.828         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.828         # on junk -- unless we have to)
2025-07-02 06:41:18.828         for j in range(blo, bhi):
2025-07-02 06:41:18.828             bj = b[j]
2025-07-02 06:41:18.828             cruncher.set_seq2(bj)
2025-07-02 06:41:18.828             for i in range(alo, ahi):
2025-07-02 06:41:18.828                 ai = a[i]
2025-07-02 06:41:18.828                 if ai == bj:
2025-07-02 06:41:18.828                     if eqi is None:
2025-07-02 06:41:18.828                         eqi, eqj = i, j
2025-07-02 06:41:18.828                     continue
2025-07-02 06:41:18.828                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.828                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.828                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.829                 # compares by a factor of 3.
2025-07-02 06:41:18.829                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.829                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.829                 # of the computation is cached by cruncher
2025-07-02 06:41:18.829                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.829                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.829                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.829                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.829         if best_ratio < cutoff:
2025-07-02 06:41:18.829             # no non-identical "pretty close" pair
2025-07-02 06:41:18.829             if eqi is None:
2025-07-02 06:41:18.829                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.829                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.829                 return
2025-07-02 06:41:18.829             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.829             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.829         else:
2025-07-02 06:41:18.829             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.829             eqi = None
2025-07-02 06:41:18.829
2025-07-02 06:41:18.830         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.830         # identical
2025-07-02 06:41:18.830
2025-07-02 06:41:18.830         # pump out diffs from before the synch point
2025-07-02 06:41:18.830         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.830
2025-07-02 06:41:18.830         # do intraline marking on the synch pair
2025-07-02 06:41:18.830         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.830         if eqi is None:
2025-07-02 06:41:18.830             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.830             atags = btags = ""
2025-07-02 06:41:18.830             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.830             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.830                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.830                 if tag == 'replace':
2025-07-02 06:41:18.830                     atags += '^' * la
2025-07-02 06:41:18.830                     btags += '^' * lb
2025-07-02 06:41:18.830                 elif tag == 'delete':
2025-07-02 06:41:18.830                     atags += '-' * la
2025-07-02 06:41:18.830                 elif tag == 'insert':
2025-07-02 06:41:18.831                     btags += '+' * lb
2025-07-02 06:41:18.831                 elif tag == 'equal':
2025-07-02 06:41:18.831                     atags += ' ' * la
2025-07-02 06:41:18.831                     btags += ' ' * lb
2025-07-02 06:41:18.831                 else:
2025-07-02 06:41:18.831                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.831             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.831         else:
2025-07-02 06:41:18.831             # the synch pair is identical
2025-07-02 06:41:18.831             yield '  ' + aelt
2025-07-02 06:41:18.831
2025-07-02 06:41:18.831         # pump out diffs from after the synch point
2025-07-02 06:41:18.831 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.831
2025-07-02 06:41:18.831 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.831 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.831
2025-07-02 06:41:18.832 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.832 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.832 alo = 467, ahi = 1101
2025-07-02 06:41:18.832 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.832 blo = 467, bhi = 1101
2025-07-02 06:41:18.832
2025-07-02 06:41:18.832     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.832         g = []
2025-07-02 06:41:18.832         if alo < ahi:
2025-07-02 06:41:18.832             if blo < bhi:
2025-07-02 06:41:18.832                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.832             else:
2025-07-02 06:41:18.832                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.832         elif blo < bhi:
2025-07-02 06:41:18.832             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.832
2025-07-02 06:41:18.832 >       yield from g
2025-07-02 06:41:18.832
2025-07-02 06:41:18.832 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.833 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.833
2025-07-02 06:41:18.833 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.833 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.833 alo = 467, ahi = 1101
2025-07-02 06:41:18.833 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.833 blo = 467, bhi = 1101
2025-07-02 06:41:18.833
2025-07-02 06:41:18.833     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.833         r"""
2025-07-02 06:41:18.833         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.833         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.833         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.833         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.833
2025-07-02 06:41:18.833         Example:
2025-07-02 06:41:18.833
2025-07-02 06:41:18.833         >>> d = Differ()
2025-07-02 06:41:18.833         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.834         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.834         >>> print(''.join(results), end="")
2025-07-02 06:41:18.834         - abcDefghiJkl
2025-07-02 06:41:18.834         + abcdefGhijkl
2025-07-02 06:41:18.834         """
2025-07-02 06:41:18.834
2025-07-02 06:41:18.834         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.834         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.834         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.834         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.834         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.834
2025-07-02 06:41:18.834         # search for the pair that matches best without being identical
2025-07-02 06:41:18.834         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.834         # on junk -- unless we have to)
2025-07-02 06:41:18.834         for j in range(blo, bhi):
2025-07-02 06:41:18.834             bj = b[j]
2025-07-02 06:41:18.834             cruncher.set_seq2(bj)
2025-07-02 06:41:18.835             for i in range(alo, ahi):
2025-07-02 06:41:18.835                 ai = a[i]
2025-07-02 06:41:18.835                 if ai == bj:
2025-07-02 06:41:18.835                     if eqi is None:
2025-07-02 06:41:18.835                         eqi, eqj = i, j
2025-07-02 06:41:18.835                     continue
2025-07-02 06:41:18.835                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.835                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.835                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.835                 # compares by a factor of 3.
2025-07-02 06:41:18.835                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.835                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.835                 # of the computation is cached by cruncher
2025-07-02 06:41:18.835                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.835                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.835                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.835                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.836         if best_ratio < cutoff:
2025-07-02 06:41:18.836             # no non-identical "pretty close" pair
2025-07-02 06:41:18.836             if eqi is None:
2025-07-02 06:41:18.836                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.836                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.836                 return
2025-07-02 06:41:18.836             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.836             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.836         else:
2025-07-02 06:41:18.836             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.836             eqi = None
2025-07-02 06:41:18.836
2025-07-02 06:41:18.836         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.836         # identical
2025-07-02 06:41:18.836
2025-07-02 06:41:18.836         # pump out diffs from before the synch point
2025-07-02 06:41:18.836         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.836
2025-07-02 06:41:18.836         # do intraline marking on the synch pair
2025-07-02 06:41:18.836         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.837         if eqi is None:
2025-07-02 06:41:18.837             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.837             atags = btags = ""
2025-07-02 06:41:18.837             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.837             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.837                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.837                 if tag == 'replace':
2025-07-02 06:41:18.837                     atags += '^' * la
2025-07-02 06:41:18.837                     btags += '^' * lb
2025-07-02 06:41:18.837                 elif tag == 'delete':
2025-07-02 06:41:18.837                     atags += '-' * la
2025-07-02 06:41:18.837                 elif tag == 'insert':
2025-07-02 06:41:18.837                     btags += '+' * lb
2025-07-02 06:41:18.837                 elif tag == 'equal':
2025-07-02 06:41:18.837                     atags += ' ' * la
2025-07-02 06:41:18.837                     btags += ' ' * lb
2025-07-02 06:41:18.837                 else:
2025-07-02 06:41:18.837                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.837             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.837         else:
2025-07-02 06:41:18.838             # the synch pair is identical
2025-07-02 06:41:18.838             yield '  ' + aelt
2025-07-02 06:41:18.838
2025-07-02 06:41:18.838         # pump out diffs from after the synch point
2025-07-02 06:41:18.838 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.838
2025-07-02 06:41:18.838 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.838 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.838
2025-07-02 06:41:18.838 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.838 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.838 alo = 468, ahi = 1101
2025-07-02 06:41:18.838 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.838 blo = 468, bhi = 1101
2025-07-02 06:41:18.838
2025-07-02 06:41:18.838     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.838         g = []
2025-07-02 06:41:18.838         if alo < ahi:
2025-07-02 06:41:18.838             if blo < bhi:
2025-07-02 06:41:18.838                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.839             else:
2025-07-02 06:41:18.839                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.839         elif blo < bhi:
2025-07-02 06:41:18.839             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.839
2025-07-02 06:41:18.839 >       yield from g
2025-07-02 06:41:18.839
2025-07-02 06:41:18.839 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.839 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.839
2025-07-02 06:41:18.839 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.839 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.839 alo = 468, ahi = 1101
2025-07-02 06:41:18.839 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.839 blo = 468, bhi = 1101
2025-07-02 06:41:18.839
2025-07-02 06:41:18.839     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.839         r"""
2025-07-02 06:41:18.839         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.839         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.839         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.840         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.840
2025-07-02 06:41:18.840         Example:
2025-07-02 06:41:18.840
2025-07-02 06:41:18.840         >>> d = Differ()
2025-07-02 06:41:18.840         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.840         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.840         >>> print(''.join(results), end="")
2025-07-02 06:41:18.840         - abcDefghiJkl
2025-07-02 06:41:18.840         + abcdefGhijkl
2025-07-02 06:41:18.840         """
2025-07-02 06:41:18.840
2025-07-02 06:41:18.840         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.840         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.840         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.840         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.841         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.841
2025-07-02 06:41:18.841         # search for the pair that matches best without being identical
2025-07-02 06:41:18.841         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.841         # on junk -- unless we have to)
2025-07-02 06:41:18.841         for j in range(blo, bhi):
2025-07-02 06:41:18.841             bj = b[j]
2025-07-02 06:41:18.841             cruncher.set_seq2(bj)
2025-07-02 06:41:18.841             for i in range(alo, ahi):
2025-07-02 06:41:18.841                 ai = a[i]
2025-07-02 06:41:18.841                 if ai == bj:
2025-07-02 06:41:18.841                     if eqi is None:
2025-07-02 06:41:18.841                         eqi, eqj = i, j
2025-07-02 06:41:18.841                     continue
2025-07-02 06:41:18.841                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.841                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.841                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.841                 # compares by a factor of 3.
2025-07-02 06:41:18.841                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.842                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.842                 # of the computation is cached by cruncher
2025-07-02 06:41:18.842                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.842                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.842                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.842                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.842         if best_ratio < cutoff:
2025-07-02 06:41:18.842             # no non-identical "pretty close" pair
2025-07-02 06:41:18.842             if eqi is None:
2025-07-02 06:41:18.842                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.842                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.842                 return
2025-07-02 06:41:18.842             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.842             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.842         else:
2025-07-02 06:41:18.842             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.842             eqi = None
2025-07-02 06:41:18.842
2025-07-02 06:41:18.842         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.842         # identical
2025-07-02 06:41:18.843
2025-07-02 06:41:18.843         # pump out diffs from before the synch point
2025-07-02 06:41:18.843         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.843
2025-07-02 06:41:18.843         # do intraline marking on the synch pair
2025-07-02 06:41:18.843         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.843         if eqi is None:
2025-07-02 06:41:18.843             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.843             atags = btags = ""
2025-07-02 06:41:18.843             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.843             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.843                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.843                 if tag == 'replace':
2025-07-02 06:41:18.843                     atags += '^' * la
2025-07-02 06:41:18.843                     btags += '^' * lb
2025-07-02 06:41:18.843                 elif tag == 'delete':
2025-07-02 06:41:18.843                     atags += '-' * la
2025-07-02 06:41:18.843                 elif tag == 'insert':
2025-07-02 06:41:18.843                     btags += '+' * lb
2025-07-02 06:41:18.844                 elif tag == 'equal':
2025-07-02 06:41:18.844                     atags += ' ' * la
2025-07-02 06:41:18.844                     btags += ' ' * lb
2025-07-02 06:41:18.844                 else:
2025-07-02 06:41:18.844                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.844             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.844         else:
2025-07-02 06:41:18.844             # the synch pair is identical
2025-07-02 06:41:18.844             yield '  ' + aelt
2025-07-02 06:41:18.844
2025-07-02 06:41:18.844         # pump out diffs from after the synch point
2025-07-02 06:41:18.844 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.844
2025-07-02 06:41:18.844 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.844 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.844
2025-07-02 06:41:18.844 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.844 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.844 alo = 469, ahi = 1101
2025-07-02 06:41:18.844 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.845 blo = 469, bhi = 1101
2025-07-02 06:41:18.845
2025-07-02 06:41:18.845     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.845         g = []
2025-07-02 06:41:18.845         if alo < ahi:
2025-07-02 06:41:18.845             if blo < bhi:
2025-07-02 06:41:18.845                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.845             else:
2025-07-02 06:41:18.845                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.845         elif blo < bhi:
2025-07-02 06:41:18.845             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.845
2025-07-02 06:41:18.845 >       yield from g
2025-07-02 06:41:18.845
2025-07-02 06:41:18.845 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.845 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.845
2025-07-02 06:41:18.845 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.845 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.845 alo = 469, ahi = 1101
2025-07-02 06:41:18.846 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.846 blo = 469, bhi = 1101
2025-07-02 06:41:18.846
2025-07-02 06:41:18.846     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.846         r"""
2025-07-02 06:41:18.846         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.846         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.846         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.846         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.846
2025-07-02 06:41:18.846         Example:
2025-07-02 06:41:18.846
2025-07-02 06:41:18.846         >>> d = Differ()
2025-07-02 06:41:18.846         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.846         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.846         >>> print(''.join(results), end="")
2025-07-02 06:41:18.846         - abcDefghiJkl
2025-07-02 06:41:18.846         + abcdefGhijkl
2025-07-02 06:41:18.847         """
2025-07-02 06:41:18.847
2025-07-02 06:41:18.847         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.847         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.847         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.847         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.847         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.847
2025-07-02 06:41:18.847         # search for the pair that matches best without being identical
2025-07-02 06:41:18.847         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.847         # on junk -- unless we have to)
2025-07-02 06:41:18.847         for j in range(blo, bhi):
2025-07-02 06:41:18.847             bj = b[j]
2025-07-02 06:41:18.847             cruncher.set_seq2(bj)
2025-07-02 06:41:18.847             for i in range(alo, ahi):
2025-07-02 06:41:18.847                 ai = a[i]
2025-07-02 06:41:18.847                 if ai == bj:
2025-07-02 06:41:18.847                     if eqi is None:
2025-07-02 06:41:18.848                         eqi, eqj = i, j
2025-07-02 06:41:18.848                     continue
2025-07-02 06:41:18.848                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.848                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.848                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.848                 # compares by a factor of 3.
2025-07-02 06:41:18.848                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.848                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.848                 # of the computation is cached by cruncher
2025-07-02 06:41:18.848                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.848                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.848                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.848                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.848         if best_ratio < cutoff:
2025-07-02 06:41:18.848             # no non-identical "pretty close" pair
2025-07-02 06:41:18.848             if eqi is None:
2025-07-02 06:41:18.848                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.848                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.848                 return
2025-07-02 06:41:18.848             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.849             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.849         else:
2025-07-02 06:41:18.849             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.849             eqi = None
2025-07-02 06:41:18.849
2025-07-02 06:41:18.849         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.849         # identical
2025-07-02 06:41:18.849
2025-07-02 06:41:18.849         # pump out diffs from before the synch point
2025-07-02 06:41:18.849         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.849
2025-07-02 06:41:18.849         # do intraline marking on the synch pair
2025-07-02 06:41:18.849         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.849         if eqi is None:
2025-07-02 06:41:18.849             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.849             atags = btags = ""
2025-07-02 06:41:18.849             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.849             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.849                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.850                 if tag == 'replace':
2025-07-02 06:41:18.850                     atags += '^' * la
2025-07-02 06:41:18.850                     btags += '^' * lb
2025-07-02 06:41:18.850                 elif tag == 'delete':
2025-07-02 06:41:18.850                     atags += '-' * la
2025-07-02 06:41:18.850                 elif tag == 'insert':
2025-07-02 06:41:18.850                     btags += '+' * lb
2025-07-02 06:41:18.850                 elif tag == 'equal':
2025-07-02 06:41:18.850                     atags += ' ' * la
2025-07-02 06:41:18.850                     btags += ' ' * lb
2025-07-02 06:41:18.850                 else:
2025-07-02 06:41:18.850                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.850             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.850         else:
2025-07-02 06:41:18.850             # the synch pair is identical
2025-07-02 06:41:18.850             yield '  ' + aelt
2025-07-02 06:41:18.850
2025-07-02 06:41:18.850         # pump out diffs from after the synch point
2025-07-02 06:41:18.850 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.851
2025-07-02 06:41:18.851 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.851 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.851
2025-07-02 06:41:18.851 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.851 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.851 alo = 470, ahi = 1101
2025-07-02 06:41:18.851 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.851 blo = 470, bhi = 1101
2025-07-02 06:41:18.851
2025-07-02 06:41:18.851     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.851         g = []
2025-07-02 06:41:18.851         if alo < ahi:
2025-07-02 06:41:18.851             if blo < bhi:
2025-07-02 06:41:18.851                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.851             else:
2025-07-02 06:41:18.851                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.851         elif blo < bhi:
2025-07-02 06:41:18.851             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.851
2025-07-02 06:41:18.852 >       yield from g
2025-07-02 06:41:18.852
2025-07-02 06:41:18.852 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.852 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.852
2025-07-02 06:41:18.852 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.852 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.852 alo = 470, ahi = 1101
2025-07-02 06:41:18.852 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.852 blo = 470, bhi = 1101
2025-07-02 06:41:18.852
2025-07-02 06:41:18.852     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.852         r"""
2025-07-02 06:41:18.852         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.852         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.852         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.852         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.852
2025-07-02 06:41:18.852         Example:
2025-07-02 06:41:18.852
2025-07-02 06:41:18.853         >>> d = Differ()
2025-07-02 06:41:18.853         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.853         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.853         >>> print(''.join(results), end="")
2025-07-02 06:41:18.853         - abcDefghiJkl
2025-07-02 06:41:18.853         + abcdefGhijkl
2025-07-02 06:41:18.853         """
2025-07-02 06:41:18.853
2025-07-02 06:41:18.853         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.853         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.853         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.853         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.853         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.853
2025-07-02 06:41:18.853         # search for the pair that matches best without being identical
2025-07-02 06:41:18.853         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.853         # on junk -- unless we have to)
2025-07-02 06:41:18.853         for j in range(blo, bhi):
2025-07-02 06:41:18.854             bj = b[j]
2025-07-02 06:41:18.854             cruncher.set_seq2(bj)
2025-07-02 06:41:18.854             for i in range(alo, ahi):
2025-07-02 06:41:18.854                 ai = a[i]
2025-07-02 06:41:18.854                 if ai == bj:
2025-07-02 06:41:18.854                     if eqi is None:
2025-07-02 06:41:18.854                         eqi, eqj = i, j
2025-07-02 06:41:18.854                     continue
2025-07-02 06:41:18.854                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.854                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.854                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.854                 # compares by a factor of 3.
2025-07-02 06:41:18.854                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.854                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.854                 # of the computation is cached by cruncher
2025-07-02 06:41:18.854                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.854                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.854                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.854                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.854         if best_ratio < cutoff:
2025-07-02 06:41:18.855             # no non-identical "pretty close" pair
2025-07-02 06:41:18.855             if eqi is None:
2025-07-02 06:41:18.855                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.855                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.855                 return
2025-07-02 06:41:18.855             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.855             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.855         else:
2025-07-02 06:41:18.855             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.855             eqi = None
2025-07-02 06:41:18.855
2025-07-02 06:41:18.855         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.855         # identical
2025-07-02 06:41:18.855
2025-07-02 06:41:18.855         # pump out diffs from before the synch point
2025-07-02 06:41:18.855         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.855
2025-07-02 06:41:18.855         # do intraline marking on the synch pair
2025-07-02 06:41:18.855         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.855         if eqi is None:
2025-07-02 06:41:18.855             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.856             atags = btags = ""
2025-07-02 06:41:18.856             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.856             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.856                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.856                 if tag == 'replace':
2025-07-02 06:41:18.856                     atags += '^' * la
2025-07-02 06:41:18.856                     btags += '^' * lb
2025-07-02 06:41:18.856                 elif tag == 'delete':
2025-07-02 06:41:18.856                     atags += '-' * la
2025-07-02 06:41:18.856                 elif tag == 'insert':
2025-07-02 06:41:18.856                     btags += '+' * lb
2025-07-02 06:41:18.856                 elif tag == 'equal':
2025-07-02 06:41:18.856                     atags += ' ' * la
2025-07-02 06:41:18.856                     btags += ' ' * lb
2025-07-02 06:41:18.856                 else:
2025-07-02 06:41:18.856                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.856             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.856         else:
2025-07-02 06:41:18.856             # the synch pair is identical
2025-07-02 06:41:18.856             yield '  ' + aelt
2025-07-02 06:41:18.857
2025-07-02 06:41:18.857         # pump out diffs from after the synch point
2025-07-02 06:41:18.857 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.857
2025-07-02 06:41:18.857 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.857 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.857
2025-07-02 06:41:18.857 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.857 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.857 alo = 471, ahi = 1101
2025-07-02 06:41:18.857 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.857 blo = 471, bhi = 1101
2025-07-02 06:41:18.857
2025-07-02 06:41:18.857     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.857         g = []
2025-07-02 06:41:18.857         if alo < ahi:
2025-07-02 06:41:18.857             if blo < bhi:
2025-07-02 06:41:18.857                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.857             else:
2025-07-02 06:41:18.858                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.858         elif blo < bhi:
2025-07-02 06:41:18.858             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.858
2025-07-02 06:41:18.858 >       yield from g
2025-07-02 06:41:18.858
2025-07-02 06:41:18.858 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.858 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.858
2025-07-02 06:41:18.858 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.858 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.858 alo = 471, ahi = 1101
2025-07-02 06:41:18.858 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.858 blo = 471, bhi = 1101
2025-07-02 06:41:18.858
2025-07-02 06:41:18.858     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.858         r"""
2025-07-02 06:41:18.858         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.858         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.858         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.859         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.859
2025-07-02 06:41:18.859         Example:
2025-07-02 06:41:18.859
2025-07-02 06:41:18.859         >>> d = Differ()
2025-07-02 06:41:18.859         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.859         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.859         >>> print(''.join(results), end="")
2025-07-02 06:41:18.859         - abcDefghiJkl
2025-07-02 06:41:18.859         + abcdefGhijkl
2025-07-02 06:41:18.859         """
2025-07-02 06:41:18.859
2025-07-02 06:41:18.859         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.859         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.859         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.859         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.860         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.860
2025-07-02 06:41:18.860         # search for the pair that matches best without being identical
2025-07-02 06:41:18.860         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.860         # on junk -- unless we have to)
2025-07-02 06:41:18.860         for j in range(blo, bhi):
2025-07-02 06:41:18.860             bj = b[j]
2025-07-02 06:41:18.860             cruncher.set_seq2(bj)
2025-07-02 06:41:18.860             for i in range(alo, ahi):
2025-07-02 06:41:18.860                 ai = a[i]
2025-07-02 06:41:18.860                 if ai == bj:
2025-07-02 06:41:18.860                     if eqi is None:
2025-07-02 06:41:18.860                         eqi, eqj = i, j
2025-07-02 06:41:18.860                     continue
2025-07-02 06:41:18.860                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.860                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.860                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.860                 # compares by a factor of 3.
2025-07-02 06:41:18.860                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.861                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.861                 # of the computation is cached by cruncher
2025-07-02 06:41:18.861                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.861                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.861                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.861                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.861         if best_ratio < cutoff:
2025-07-02 06:41:18.861             # no non-identical "pretty close" pair
2025-07-02 06:41:18.861             if eqi is None:
2025-07-02 06:41:18.861                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.861                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.861                 return
2025-07-02 06:41:18.861             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.861             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.861         else:
2025-07-02 06:41:18.861             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.861             eqi = None
2025-07-02 06:41:18.861
2025-07-02 06:41:18.861         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.862         # identical
2025-07-02 06:41:18.862
2025-07-02 06:41:18.862         # pump out diffs from before the synch point
2025-07-02 06:41:18.862         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.862
2025-07-02 06:41:18.862         # do intraline marking on the synch pair
2025-07-02 06:41:18.862         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.862         if eqi is None:
2025-07-02 06:41:18.862             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.862             atags = btags = ""
2025-07-02 06:41:18.862             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.862             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.862                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.862                 if tag == 'replace':
2025-07-02 06:41:18.862                     atags += '^' * la
2025-07-02 06:41:18.862                     btags += '^' * lb
2025-07-02 06:41:18.862                 elif tag == 'delete':
2025-07-02 06:41:18.862                     atags += '-' * la
2025-07-02 06:41:18.862                 elif tag == 'insert':
2025-07-02 06:41:18.862                     btags += '+' * lb
2025-07-02 06:41:18.863                 elif tag == 'equal':
2025-07-02 06:41:18.863                     atags += ' ' * la
2025-07-02 06:41:18.863                     btags += ' ' * lb
2025-07-02 06:41:18.863                 else:
2025-07-02 06:41:18.863                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.863             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.863         else:
2025-07-02 06:41:18.863             # the synch pair is identical
2025-07-02 06:41:18.863             yield '  ' + aelt
2025-07-02 06:41:18.863
2025-07-02 06:41:18.863         # pump out diffs from after the synch point
2025-07-02 06:41:18.863 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.863
2025-07-02 06:41:18.863 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.863 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.864
2025-07-02 06:41:18.864 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.864 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.864 alo = 472, ahi = 1101
2025-07-02 06:41:18.864 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.864 blo = 472, bhi = 1101
2025-07-02 06:41:18.864
2025-07-02 06:41:18.864     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.864         g = []
2025-07-02 06:41:18.864         if alo < ahi:
2025-07-02 06:41:18.864             if blo < bhi:
2025-07-02 06:41:18.864                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.864             else:
2025-07-02 06:41:18.864                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.864         elif blo < bhi:
2025-07-02 06:41:18.864             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.864
2025-07-02 06:41:18.864 >       yield from g
2025-07-02 06:41:18.864
2025-07-02 06:41:18.864 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.865 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.865
2025-07-02 06:41:18.865 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.865 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.865 alo = 472, ahi = 1101
2025-07-02 06:41:18.865 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.865 blo = 472, bhi = 1101
2025-07-02 06:41:18.865
2025-07-02 06:41:18.865     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.865         r"""
2025-07-02 06:41:18.865         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.865         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.865         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.865         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.865
2025-07-02 06:41:18.865         Example:
2025-07-02 06:41:18.865
2025-07-02 06:41:18.866         >>> d = Differ()
2025-07-02 06:41:18.866         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.866         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.866         >>> print(''.join(results), end="")
2025-07-02 06:41:18.866         - abcDefghiJkl
2025-07-02 06:41:18.866         + abcdefGhijkl
2025-07-02 06:41:18.866         """
2025-07-02 06:41:18.866
2025-07-02 06:41:18.866         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.866         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.866         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.866         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.866         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.866
2025-07-02 06:41:18.866         # search for the pair that matches best without being identical
2025-07-02 06:41:18.866         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.866         # on junk -- unless we have to)
2025-07-02 06:41:18.867         for j in range(blo, bhi):
2025-07-02 06:41:18.867             bj = b[j]
2025-07-02 06:41:18.867             cruncher.set_seq2(bj)
2025-07-02 06:41:18.867             for i in range(alo, ahi):
2025-07-02 06:41:18.867                 ai = a[i]
2025-07-02 06:41:18.867                 if ai == bj:
2025-07-02 06:41:18.867                     if eqi is None:
2025-07-02 06:41:18.867                         eqi, eqj = i, j
2025-07-02 06:41:18.867                     continue
2025-07-02 06:41:18.867                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.867                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.867                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.867                 # compares by a factor of 3.
2025-07-02 06:41:18.867                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.867                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.867                 # of the computation is cached by cruncher
2025-07-02 06:41:18.867                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.867                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.868                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.868                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.868         if best_ratio < cutoff:
2025-07-02 06:41:18.868             # no non-identical "pretty close" pair
2025-07-02 06:41:18.868             if eqi is None:
2025-07-02 06:41:18.868                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.868                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.868                 return
2025-07-02 06:41:18.868             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.868             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.868         else:
2025-07-02 06:41:18.868             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.868             eqi = None
2025-07-02 06:41:18.868
2025-07-02 06:41:18.868         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.868         # identical
2025-07-02 06:41:18.868
2025-07-02 06:41:18.868         # pump out diffs from before the synch point
2025-07-02 06:41:18.868         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.869
2025-07-02 06:41:18.869         # do intraline marking on the synch pair
2025-07-02 06:41:18.869         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.869         if eqi is None:
2025-07-02 06:41:18.869             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.869             atags = btags = ""
2025-07-02 06:41:18.869             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.869             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.869                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.869                 if tag == 'replace':
2025-07-02 06:41:18.869                     atags += '^' * la
2025-07-02 06:41:18.869                     btags += '^' * lb
2025-07-02 06:41:18.869                 elif tag == 'delete':
2025-07-02 06:41:18.869                     atags += '-' * la
2025-07-02 06:41:18.869                 elif tag == 'insert':
2025-07-02 06:41:18.869                     btags += '+' * lb
2025-07-02 06:41:18.869                 elif tag == 'equal':
2025-07-02 06:41:18.869                     atags += ' ' * la
2025-07-02 06:41:18.869                     btags += ' ' * lb
2025-07-02 06:41:18.869                 else:
2025-07-02 06:41:18.869                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.870             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.870         else:
2025-07-02 06:41:18.870             # the synch pair is identical
2025-07-02 06:41:18.870             yield '  ' + aelt
2025-07-02 06:41:18.870
2025-07-02 06:41:18.870         # pump out diffs from after the synch point
2025-07-02 06:41:18.870 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.870
2025-07-02 06:41:18.870 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.870 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.870
2025-07-02 06:41:18.870 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.870 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.870 alo = 473, ahi = 1101
2025-07-02 06:41:18.870 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.870 blo = 473, bhi = 1101
2025-07-02 06:41:18.870
2025-07-02 06:41:18.870     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.870         g = []
2025-07-02 06:41:18.870         if alo < ahi:
2025-07-02 06:41:18.871             if blo < bhi:
2025-07-02 06:41:18.871                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.871             else:
2025-07-02 06:41:18.871                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.871         elif blo < bhi:
2025-07-02 06:41:18.871             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.871
2025-07-02 06:41:18.871 >       yield from g
2025-07-02 06:41:18.871
2025-07-02 06:41:18.871 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.871 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.871
2025-07-02 06:41:18.871 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.871 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.871 alo = 473, ahi = 1101
2025-07-02 06:41:18.871 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.871 blo = 473, bhi = 1101
2025-07-02 06:41:18.871
2025-07-02 06:41:18.871     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.871         r"""
2025-07-02 06:41:18.872         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.872         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.872         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.872         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.872
2025-07-02 06:41:18.872         Example:
2025-07-02 06:41:18.872
2025-07-02 06:41:18.872         >>> d = Differ()
2025-07-02 06:41:18.872         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.872         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.872         >>> print(''.join(results), end="")
2025-07-02 06:41:18.872         - abcDefghiJkl
2025-07-02 06:41:18.872         + abcdefGhijkl
2025-07-02 06:41:18.872         """
2025-07-02 06:41:18.872
2025-07-02 06:41:18.872         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.872         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.872         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.873         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.873         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.873
2025-07-02 06:41:18.873         # search for the pair that matches best without being identical
2025-07-02 06:41:18.873         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.873         # on junk -- unless we have to)
2025-07-02 06:41:18.873         for j in range(blo, bhi):
2025-07-02 06:41:18.873             bj = b[j]
2025-07-02 06:41:18.873             cruncher.set_seq2(bj)
2025-07-02 06:41:18.873             for i in range(alo, ahi):
2025-07-02 06:41:18.873                 ai = a[i]
2025-07-02 06:41:18.873                 if ai == bj:
2025-07-02 06:41:18.873                     if eqi is None:
2025-07-02 06:41:18.873                         eqi, eqj = i, j
2025-07-02 06:41:18.873                     continue
2025-07-02 06:41:18.873                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.873                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.873                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.873                 # compares by a factor of 3.
2025-07-02 06:41:18.873                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.874                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.874                 # of the computation is cached by cruncher
2025-07-02 06:41:18.874                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.874                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.874                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.874                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.874         if best_ratio < cutoff:
2025-07-02 06:41:18.874             # no non-identical "pretty close" pair
2025-07-02 06:41:18.874             if eqi is None:
2025-07-02 06:41:18.874                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.874                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.874                 return
2025-07-02 06:41:18.874             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.874             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.874         else:
2025-07-02 06:41:18.874             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.874             eqi = None
2025-07-02 06:41:18.874
2025-07-02 06:41:18.874         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.874         # identical
2025-07-02 06:41:18.875
2025-07-02 06:41:18.875         # pump out diffs from before the synch point
2025-07-02 06:41:18.875         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.875
2025-07-02 06:41:18.875         # do intraline marking on the synch pair
2025-07-02 06:41:18.875         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.875         if eqi is None:
2025-07-02 06:41:18.875             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.875             atags = btags = ""
2025-07-02 06:41:18.875             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.875             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.875                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.875                 if tag == 'replace':
2025-07-02 06:41:18.875                     atags += '^' * la
2025-07-02 06:41:18.875                     btags += '^' * lb
2025-07-02 06:41:18.875                 elif tag == 'delete':
2025-07-02 06:41:18.875                     atags += '-' * la
2025-07-02 06:41:18.875                 elif tag == 'insert':
2025-07-02 06:41:18.875                     btags += '+' * lb
2025-07-02 06:41:18.875                 elif tag == 'equal':
2025-07-02 06:41:18.876                     atags += ' ' * la
2025-07-02 06:41:18.876                     btags += ' ' * lb
2025-07-02 06:41:18.876                 else:
2025-07-02 06:41:18.876                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.876             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.876         else:
2025-07-02 06:41:18.876             # the synch pair is identical
2025-07-02 06:41:18.876             yield '  ' + aelt
2025-07-02 06:41:18.876
2025-07-02 06:41:18.876         # pump out diffs from after the synch point
2025-07-02 06:41:18.876 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.876
2025-07-02 06:41:18.876 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.876 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.876
2025-07-02 06:41:18.876 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.876 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.876 alo = 474, ahi = 1101
2025-07-02 06:41:18.877 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.877 blo = 474, bhi = 1101
2025-07-02 06:41:18.877
2025-07-02 06:41:18.877     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.877         g = []
2025-07-02 06:41:18.877         if alo < ahi:
2025-07-02 06:41:18.877             if blo < bhi:
2025-07-02 06:41:18.877                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.877             else:
2025-07-02 06:41:18.877                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.877         elif blo < bhi:
2025-07-02 06:41:18.877             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.877
2025-07-02 06:41:18.877 >       yield from g
2025-07-02 06:41:18.877
2025-07-02 06:41:18.877 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.877 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.877
2025-07-02 06:41:18.877 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.878 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.878 alo = 474, ahi = 1101
2025-07-02 06:41:18.878 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.878 blo = 474, bhi = 1101
2025-07-02 06:41:18.878
2025-07-02 06:41:18.878     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.878         r"""
2025-07-02 06:41:18.878         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.878         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.878         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.878         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.878
2025-07-02 06:41:18.878         Example:
2025-07-02 06:41:18.878
2025-07-02 06:41:18.878         >>> d = Differ()
2025-07-02 06:41:18.878         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.878         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.878         >>> print(''.join(results), end="")
2025-07-02 06:41:18.878         - abcDefghiJkl
2025-07-02 06:41:18.879         + abcdefGhijkl
2025-07-02 06:41:18.879         """
2025-07-02 06:41:18.879
2025-07-02 06:41:18.879         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.879         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.879         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.879         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.879         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.879
2025-07-02 06:41:18.879         # search for the pair that matches best without being identical
2025-07-02 06:41:18.879         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.879         # on junk -- unless we have to)
2025-07-02 06:41:18.879         for j in range(blo, bhi):
2025-07-02 06:41:18.879             bj = b[j]
2025-07-02 06:41:18.879             cruncher.set_seq2(bj)
2025-07-02 06:41:18.879             for i in range(alo, ahi):
2025-07-02 06:41:18.879                 ai = a[i]
2025-07-02 06:41:18.879                 if ai == bj:
2025-07-02 06:41:18.880                     if eqi is None:
2025-07-02 06:41:18.880                         eqi, eqj = i, j
2025-07-02 06:41:18.880                     continue
2025-07-02 06:41:18.880                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.880                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.880                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.880                 # compares by a factor of 3.
2025-07-02 06:41:18.880                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.880                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.880                 # of the computation is cached by cruncher
2025-07-02 06:41:18.880                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.880                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.880                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.880                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.880         if best_ratio < cutoff:
2025-07-02 06:41:18.880             # no non-identical "pretty close" pair
2025-07-02 06:41:18.880             if eqi is None:
2025-07-02 06:41:18.880                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.880                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.881                 return
2025-07-02 06:41:18.881             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.881             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.881         else:
2025-07-02 06:41:18.881             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.881             eqi = None
2025-07-02 06:41:18.881
2025-07-02 06:41:18.881         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.881         # identical
2025-07-02 06:41:18.881
2025-07-02 06:41:18.881         # pump out diffs from before the synch point
2025-07-02 06:41:18.881         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.881
2025-07-02 06:41:18.881         # do intraline marking on the synch pair
2025-07-02 06:41:18.881         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.881         if eqi is None:
2025-07-02 06:41:18.881             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.881             atags = btags = ""
2025-07-02 06:41:18.881             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.881             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.881                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.882                 if tag == 'replace':
2025-07-02 06:41:18.882                     atags += '^' * la
2025-07-02 06:41:18.882                     btags += '^' * lb
2025-07-02 06:41:18.882                 elif tag == 'delete':
2025-07-02 06:41:18.882                     atags += '-' * la
2025-07-02 06:41:18.882                 elif tag == 'insert':
2025-07-02 06:41:18.882                     btags += '+' * lb
2025-07-02 06:41:18.882                 elif tag == 'equal':
2025-07-02 06:41:18.882                     atags += ' ' * la
2025-07-02 06:41:18.882                     btags += ' ' * lb
2025-07-02 06:41:18.882                 else:
2025-07-02 06:41:18.882                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.882             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.882         else:
2025-07-02 06:41:18.882             # the synch pair is identical
2025-07-02 06:41:18.882             yield '  ' + aelt
2025-07-02 06:41:18.882
2025-07-02 06:41:18.882         # pump out diffs from after the synch point
2025-07-02 06:41:18.882 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.882
2025-07-02 06:41:18.883 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.883 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.883
2025-07-02 06:41:18.883 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.883 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.883 alo = 475, ahi = 1101
2025-07-02 06:41:18.883 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.883 blo = 475, bhi = 1101
2025-07-02 06:41:18.883
2025-07-02 06:41:18.883     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.883         g = []
2025-07-02 06:41:18.883         if alo < ahi:
2025-07-02 06:41:18.883             if blo < bhi:
2025-07-02 06:41:18.883                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.883             else:
2025-07-02 06:41:18.883                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.883         elif blo < bhi:
2025-07-02 06:41:18.883             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.883
2025-07-02 06:41:18.883 >       yield from g
2025-07-02 06:41:18.884
2025-07-02 06:41:18.884 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.884 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.884
2025-07-02 06:41:18.884 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.884 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.884 alo = 475, ahi = 1101
2025-07-02 06:41:18.884 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.884 blo = 475, bhi = 1101
2025-07-02 06:41:18.884
2025-07-02 06:41:18.884     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.884         r"""
2025-07-02 06:41:18.884         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.884         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.884         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.884         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.884
2025-07-02 06:41:18.884         Example:
2025-07-02 06:41:18.885
2025-07-02 06:41:18.885         >>> d = Differ()
2025-07-02 06:41:18.885         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.885         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.885         >>> print(''.join(results), end="")
2025-07-02 06:41:18.885         - abcDefghiJkl
2025-07-02 06:41:18.885         + abcdefGhijkl
2025-07-02 06:41:18.885         """
2025-07-02 06:41:18.885
2025-07-02 06:41:18.885         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.885         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.885         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.885         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.885         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.885
2025-07-02 06:41:18.885         # search for the pair that matches best without being identical
2025-07-02 06:41:18.885         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.886         # on junk -- unless we have to)
2025-07-02 06:41:18.886         for j in range(blo, bhi):
2025-07-02 06:41:18.886             bj = b[j]
2025-07-02 06:41:18.886             cruncher.set_seq2(bj)
2025-07-02 06:41:18.886             for i in range(alo, ahi):
2025-07-02 06:41:18.886                 ai = a[i]
2025-07-02 06:41:18.886                 if ai == bj:
2025-07-02 06:41:18.886                     if eqi is None:
2025-07-02 06:41:18.886                         eqi, eqj = i, j
2025-07-02 06:41:18.886                     continue
2025-07-02 06:41:18.886                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.886                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.886                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.886                 # compares by a factor of 3.
2025-07-02 06:41:18.886                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.886                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.886                 # of the computation is cached by cruncher
2025-07-02 06:41:18.886                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.886                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.887                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.887                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.887         if best_ratio < cutoff:
2025-07-02 06:41:18.887             # no non-identical "pretty close" pair
2025-07-02 06:41:18.887             if eqi is None:
2025-07-02 06:41:18.887                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.887                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.887                 return
2025-07-02 06:41:18.887             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.887             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.887         else:
2025-07-02 06:41:18.887             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.887             eqi = None
2025-07-02 06:41:18.887
2025-07-02 06:41:18.887         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.887         # identical
2025-07-02 06:41:18.887
2025-07-02 06:41:18.887         # pump out diffs from before the synch point
2025-07-02 06:41:18.887         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.887
2025-07-02 06:41:18.888         # do intraline marking on the synch pair
2025-07-02 06:41:18.888         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.888         if eqi is None:
2025-07-02 06:41:18.888             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.888             atags = btags = ""
2025-07-02 06:41:18.888             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.888             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.888                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.888                 if tag == 'replace':
2025-07-02 06:41:18.888                     atags += '^' * la
2025-07-02 06:41:18.888                     btags += '^' * lb
2025-07-02 06:41:18.888                 elif tag == 'delete':
2025-07-02 06:41:18.888                     atags += '-' * la
2025-07-02 06:41:18.888                 elif tag == 'insert':
2025-07-02 06:41:18.888                     btags += '+' * lb
2025-07-02 06:41:18.888                 elif tag == 'equal':
2025-07-02 06:41:18.888                     atags += ' ' * la
2025-07-02 06:41:18.888                     btags += ' ' * lb
2025-07-02 06:41:18.888                 else:
2025-07-02 06:41:18.888                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.888             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.889         else:
2025-07-02 06:41:18.889             # the synch pair is identical
2025-07-02 06:41:18.889             yield '  ' + aelt
2025-07-02 06:41:18.889
2025-07-02 06:41:18.889         # pump out diffs from after the synch point
2025-07-02 06:41:18.889 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.889
2025-07-02 06:41:18.889 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.889 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.889
2025-07-02 06:41:18.889 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.889 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.889 alo = 476, ahi = 1101
2025-07-02 06:41:18.889 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.889 blo = 476, bhi = 1101
2025-07-02 06:41:18.889
2025-07-02 06:41:18.889     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.889         g = []
2025-07-02 06:41:18.889         if alo < ahi:
2025-07-02 06:41:18.889             if blo < bhi:
2025-07-02 06:41:18.890                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.890             else:
2025-07-02 06:41:18.890                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.890         elif blo < bhi:
2025-07-02 06:41:18.890             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.890
2025-07-02 06:41:18.890 >       yield from g
2025-07-02 06:41:18.890
2025-07-02 06:41:18.890 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.890 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.890
2025-07-02 06:41:18.890 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.890 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.890 alo = 476, ahi = 1101
2025-07-02 06:41:18.890 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.890 blo = 476, bhi = 1101
2025-07-02 06:41:18.890
2025-07-02 06:41:18.890     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.890         r"""
2025-07-02 06:41:18.890         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.891         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.891         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.891         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.891
2025-07-02 06:41:18.891         Example:
2025-07-02 06:41:18.891
2025-07-02 06:41:18.891         >>> d = Differ()
2025-07-02 06:41:18.891         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.891         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.891         >>> print(''.join(results), end="")
2025-07-02 06:41:18.891         - abcDefghiJkl
2025-07-02 06:41:18.891         + abcdefGhijkl
2025-07-02 06:41:18.891         """
2025-07-02 06:41:18.891
2025-07-02 06:41:18.891         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.891         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.891         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.891         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.892         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.892
2025-07-02 06:41:18.892         # search for the pair that matches best without being identical
2025-07-02 06:41:18.892         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.892         # on junk -- unless we have to)
2025-07-02 06:41:18.892         for j in range(blo, bhi):
2025-07-02 06:41:18.892             bj = b[j]
2025-07-02 06:41:18.892             cruncher.set_seq2(bj)
2025-07-02 06:41:18.892             for i in range(alo, ahi):
2025-07-02 06:41:18.892                 ai = a[i]
2025-07-02 06:41:18.892                 if ai == bj:
2025-07-02 06:41:18.892                     if eqi is None:
2025-07-02 06:41:18.892                         eqi, eqj = i, j
2025-07-02 06:41:18.892                     continue
2025-07-02 06:41:18.892                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.892                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.892                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.892                 # compares by a factor of 3.
2025-07-02 06:41:18.892                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.892                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.892                 # of the computation is cached by cruncher
2025-07-02 06:41:18.893                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.893                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.893                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.893                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.893         if best_ratio < cutoff:
2025-07-02 06:41:18.893             # no non-identical "pretty close" pair
2025-07-02 06:41:18.893             if eqi is None:
2025-07-02 06:41:18.893                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.893                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.893                 return
2025-07-02 06:41:18.893             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.893             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.893         else:
2025-07-02 06:41:18.893             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.893             eqi = None
2025-07-02 06:41:18.893
2025-07-02 06:41:18.893         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.894         # identical
2025-07-02 06:41:18.894
2025-07-02 06:41:18.894         # pump out diffs from before the synch point
2025-07-02 06:41:18.894         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.894
2025-07-02 06:41:18.894         # do intraline marking on the synch pair
2025-07-02 06:41:18.894         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.894         if eqi is None:
2025-07-02 06:41:18.894             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.894             atags = btags = ""
2025-07-02 06:41:18.894             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.894             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.894                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.894                 if tag == 'replace':
2025-07-02 06:41:18.894                     atags += '^' * la
2025-07-02 06:41:18.894                     btags += '^' * lb
2025-07-02 06:41:18.894                 elif tag == 'delete':
2025-07-02 06:41:18.894                     atags += '-' * la
2025-07-02 06:41:18.894                 elif tag == 'insert':
2025-07-02 06:41:18.894                     btags += '+' * lb
2025-07-02 06:41:18.895                 elif tag == 'equal':
2025-07-02 06:41:18.895                     atags += ' ' * la
2025-07-02 06:41:18.895                     btags += ' ' * lb
2025-07-02 06:41:18.895                 else:
2025-07-02 06:41:18.895                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.895             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.895         else:
2025-07-02 06:41:18.895             # the synch pair is identical
2025-07-02 06:41:18.895             yield '  ' + aelt
2025-07-02 06:41:18.895
2025-07-02 06:41:18.895         # pump out diffs from after the synch point
2025-07-02 06:41:18.895 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.895
2025-07-02 06:41:18.895 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.895 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.895
2025-07-02 06:41:18.895 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.895 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.896 alo = 477, ahi = 1101
2025-07-02 06:41:18.896 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.896 blo = 477, bhi = 1101
2025-07-02 06:41:18.896
2025-07-02 06:41:18.896     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.896         g = []
2025-07-02 06:41:18.896         if alo < ahi:
2025-07-02 06:41:18.896             if blo < bhi:
2025-07-02 06:41:18.896                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.896             else:
2025-07-02 06:41:18.896                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.896         elif blo < bhi:
2025-07-02 06:41:18.896             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.896
2025-07-02 06:41:18.896 >       yield from g
2025-07-02 06:41:18.896
2025-07-02 06:41:18.896 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.896 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.896
2025-07-02 06:41:18.896 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.897 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.897 alo = 477, ahi = 1101
2025-07-02 06:41:18.897 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.897 blo = 477, bhi = 1101
2025-07-02 06:41:18.897
2025-07-02 06:41:18.897     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.897         r"""
2025-07-02 06:41:18.897         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.897         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.897         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.897         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.897
2025-07-02 06:41:18.897         Example:
2025-07-02 06:41:18.897
2025-07-02 06:41:18.897         >>> d = Differ()
2025-07-02 06:41:18.897         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.897         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.897         >>> print(''.join(results), end="")
2025-07-02 06:41:18.897         - abcDefghiJkl
2025-07-02 06:41:18.898         + abcdefGhijkl
2025-07-02 06:41:18.898         """
2025-07-02 06:41:18.898
2025-07-02 06:41:18.898         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.898         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.898         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.898         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.898         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.898
2025-07-02 06:41:18.898         # search for the pair that matches best without being identical
2025-07-02 06:41:18.898         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.898         # on junk -- unless we have to)
2025-07-02 06:41:18.898         for j in range(blo, bhi):
2025-07-02 06:41:18.898             bj = b[j]
2025-07-02 06:41:18.898             cruncher.set_seq2(bj)
2025-07-02 06:41:18.898             for i in range(alo, ahi):
2025-07-02 06:41:18.898                 ai = a[i]
2025-07-02 06:41:18.898                 if ai == bj:
2025-07-02 06:41:18.898                     if eqi is None:
2025-07-02 06:41:18.899                         eqi, eqj = i, j
2025-07-02 06:41:18.899                     continue
2025-07-02 06:41:18.899                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.899                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.899                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.899                 # compares by a factor of 3.
2025-07-02 06:41:18.899                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.899                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.899                 # of the computation is cached by cruncher
2025-07-02 06:41:18.899                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.899                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.899                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.899                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.899         if best_ratio < cutoff:
2025-07-02 06:41:18.899             # no non-identical "pretty close" pair
2025-07-02 06:41:18.899             if eqi is None:
2025-07-02 06:41:18.899                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.899                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.899                 return
2025-07-02 06:41:18.900             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.900             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.900         else:
2025-07-02 06:41:18.900             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.900             eqi = None
2025-07-02 06:41:18.900
2025-07-02 06:41:18.900         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.900         # identical
2025-07-02 06:41:18.900
2025-07-02 06:41:18.900         # pump out diffs from before the synch point
2025-07-02 06:41:18.900         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.900
2025-07-02 06:41:18.900         # do intraline marking on the synch pair
2025-07-02 06:41:18.900         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.900         if eqi is None:
2025-07-02 06:41:18.900             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.900             atags = btags = ""
2025-07-02 06:41:18.900             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.900             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.900                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.900                 if tag == 'replace':
2025-07-02 06:41:18.901                     atags += '^' * la
2025-07-02 06:41:18.901                     btags += '^' * lb
2025-07-02 06:41:18.901                 elif tag == 'delete':
2025-07-02 06:41:18.901                     atags += '-' * la
2025-07-02 06:41:18.901                 elif tag == 'insert':
2025-07-02 06:41:18.901                     btags += '+' * lb
2025-07-02 06:41:18.901                 elif tag == 'equal':
2025-07-02 06:41:18.901                     atags += ' ' * la
2025-07-02 06:41:18.901                     btags += ' ' * lb
2025-07-02 06:41:18.901                 else:
2025-07-02 06:41:18.901                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.901             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.901         else:
2025-07-02 06:41:18.901             # the synch pair is identical
2025-07-02 06:41:18.901             yield '  ' + aelt
2025-07-02 06:41:18.901
2025-07-02 06:41:18.901         # pump out diffs from after the synch point
2025-07-02 06:41:18.901 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.901
2025-07-02 06:41:18.901 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.902 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.902
2025-07-02 06:41:18.902 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.902 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.902 alo = 478, ahi = 1101
2025-07-02 06:41:18.902 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.902 blo = 478, bhi = 1101
2025-07-02 06:41:18.902
2025-07-02 06:41:18.902     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.902         g = []
2025-07-02 06:41:18.902         if alo < ahi:
2025-07-02 06:41:18.902             if blo < bhi:
2025-07-02 06:41:18.902                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.902             else:
2025-07-02 06:41:18.902                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.902         elif blo < bhi:
2025-07-02 06:41:18.902             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.902
2025-07-02 06:41:18.902 >       yield from g
2025-07-02 06:41:18.903
2025-07-02 06:41:18.903 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.903 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.903
2025-07-02 06:41:18.903 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.903 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.903 alo = 478, ahi = 1101
2025-07-02 06:41:18.903 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.903 blo = 478, bhi = 1101
2025-07-02 06:41:18.903
2025-07-02 06:41:18.903     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.903         r"""
2025-07-02 06:41:18.903         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.903         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.903         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.903         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.903
2025-07-02 06:41:18.903         Example:
2025-07-02 06:41:18.903
2025-07-02 06:41:18.904         >>> d = Differ()
2025-07-02 06:41:18.904         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.904         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.904         >>> print(''.join(results), end="")
2025-07-02 06:41:18.904         - abcDefghiJkl
2025-07-02 06:41:18.904         + abcdefGhijkl
2025-07-02 06:41:18.904         """
2025-07-02 06:41:18.904
2025-07-02 06:41:18.904         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.904         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.904         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.904         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.904         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.904
2025-07-02 06:41:18.904         # search for the pair that matches best without being identical
2025-07-02 06:41:18.904         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.904         # on junk -- unless we have to)
2025-07-02 06:41:18.905         for j in range(blo, bhi):
2025-07-02 06:41:18.905             bj = b[j]
2025-07-02 06:41:18.905             cruncher.set_seq2(bj)
2025-07-02 06:41:18.905             for i in range(alo, ahi):
2025-07-02 06:41:18.905                 ai = a[i]
2025-07-02 06:41:18.905                 if ai == bj:
2025-07-02 06:41:18.905                     if eqi is None:
2025-07-02 06:41:18.905                         eqi, eqj = i, j
2025-07-02 06:41:18.905                     continue
2025-07-02 06:41:18.905                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.905                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.905                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.905                 # compares by a factor of 3.
2025-07-02 06:41:18.905                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.905                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.905                 # of the computation is cached by cruncher
2025-07-02 06:41:18.905                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.905                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.905                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.906                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.906         if best_ratio < cutoff:
2025-07-02 06:41:18.906             # no non-identical "pretty close" pair
2025-07-02 06:41:18.906             if eqi is None:
2025-07-02 06:41:18.906                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.906                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.906                 return
2025-07-02 06:41:18.906             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.906             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.906         else:
2025-07-02 06:41:18.906             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.906             eqi = None
2025-07-02 06:41:18.906
2025-07-02 06:41:18.906         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.906         # identical
2025-07-02 06:41:18.906
2025-07-02 06:41:18.906         # pump out diffs from before the synch point
2025-07-02 06:41:18.906         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.906
2025-07-02 06:41:18.906         # do intraline marking on the synch pair
2025-07-02 06:41:18.907         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.907         if eqi is None:
2025-07-02 06:41:18.907             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.907             atags = btags = ""
2025-07-02 06:41:18.907             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.907             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.907                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.907                 if tag == 'replace':
2025-07-02 06:41:18.907                     atags += '^' * la
2025-07-02 06:41:18.907                     btags += '^' * lb
2025-07-02 06:41:18.907                 elif tag == 'delete':
2025-07-02 06:41:18.907                     atags += '-' * la
2025-07-02 06:41:18.907                 elif tag == 'insert':
2025-07-02 06:41:18.907                     btags += '+' * lb
2025-07-02 06:41:18.907                 elif tag == 'equal':
2025-07-02 06:41:18.907                     atags += ' ' * la
2025-07-02 06:41:18.907                     btags += ' ' * lb
2025-07-02 06:41:18.907                 else:
2025-07-02 06:41:18.907                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.907             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.908         else:
2025-07-02 06:41:18.908             # the synch pair is identical
2025-07-02 06:41:18.908             yield '  ' + aelt
2025-07-02 06:41:18.908
2025-07-02 06:41:18.908         # pump out diffs from after the synch point
2025-07-02 06:41:18.908 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.908
2025-07-02 06:41:18.908 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.908 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.908
2025-07-02 06:41:18.908 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.908 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.908 alo = 479, ahi = 1101
2025-07-02 06:41:18.908 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.908 blo = 479, bhi = 1101
2025-07-02 06:41:18.908
2025-07-02 06:41:18.908     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.908         g = []
2025-07-02 06:41:18.908         if alo < ahi:
2025-07-02 06:41:18.908             if blo < bhi:
2025-07-02 06:41:18.909                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.909             else:
2025-07-02 06:41:18.909                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.909         elif blo < bhi:
2025-07-02 06:41:18.909             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.909
2025-07-02 06:41:18.909 >       yield from g
2025-07-02 06:41:18.909
2025-07-02 06:41:18.909 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.909 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.909
2025-07-02 06:41:18.909 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.909 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.909 alo = 479, ahi = 1101
2025-07-02 06:41:18.909 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.909 blo = 479, bhi = 1101
2025-07-02 06:41:18.909
2025-07-02 06:41:18.909     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.909         r"""
2025-07-02 06:41:18.909         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.910         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.910         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.910         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.910
2025-07-02 06:41:18.910         Example:
2025-07-02 06:41:18.910
2025-07-02 06:41:18.910         >>> d = Differ()
2025-07-02 06:41:18.910         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.910         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.910         >>> print(''.join(results), end="")
2025-07-02 06:41:18.910         - abcDefghiJkl
2025-07-02 06:41:18.910         + abcdefGhijkl
2025-07-02 06:41:18.910         """
2025-07-02 06:41:18.910
2025-07-02 06:41:18.910         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.910         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.910         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.910         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.911         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.911
2025-07-02 06:41:18.911         # search for the pair that matches best without being identical
2025-07-02 06:41:18.911         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.911         # on junk -- unless we have to)
2025-07-02 06:41:18.911         for j in range(blo, bhi):
2025-07-02 06:41:18.911             bj = b[j]
2025-07-02 06:41:18.911             cruncher.set_seq2(bj)
2025-07-02 06:41:18.911             for i in range(alo, ahi):
2025-07-02 06:41:18.911                 ai = a[i]
2025-07-02 06:41:18.911                 if ai == bj:
2025-07-02 06:41:18.911                     if eqi is None:
2025-07-02 06:41:18.911                         eqi, eqj = i, j
2025-07-02 06:41:18.911                     continue
2025-07-02 06:41:18.911                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.911                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.911                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.911                 # compares by a factor of 3.
2025-07-02 06:41:18.912                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.912                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.912                 # of the computation is cached by cruncher
2025-07-02 06:41:18.912                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.912                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.912                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.912                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.912         if best_ratio < cutoff:
2025-07-02 06:41:18.912             # no non-identical "pretty close" pair
2025-07-02 06:41:18.912             if eqi is None:
2025-07-02 06:41:18.912                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.912                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.912                 return
2025-07-02 06:41:18.912             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.912             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.912         else:
2025-07-02 06:41:18.912             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.912             eqi = None
2025-07-02 06:41:18.912
2025-07-02 06:41:18.913         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.913         # identical
2025-07-02 06:41:18.913
2025-07-02 06:41:18.913         # pump out diffs from before the synch point
2025-07-02 06:41:18.913         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.913
2025-07-02 06:41:18.913         # do intraline marking on the synch pair
2025-07-02 06:41:18.913         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.913         if eqi is None:
2025-07-02 06:41:18.913             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.913             atags = btags = ""
2025-07-02 06:41:18.913             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.913             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.913                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.913                 if tag == 'replace':
2025-07-02 06:41:18.913                     atags += '^' * la
2025-07-02 06:41:18.913                     btags += '^' * lb
2025-07-02 06:41:18.913                 elif tag == 'delete':
2025-07-02 06:41:18.913                     atags += '-' * la
2025-07-02 06:41:18.913                 elif tag == 'insert':
2025-07-02 06:41:18.914                     btags += '+' * lb
2025-07-02 06:41:18.914                 elif tag == 'equal':
2025-07-02 06:41:18.914                     atags += ' ' * la
2025-07-02 06:41:18.914                     btags += ' ' * lb
2025-07-02 06:41:18.914                 else:
2025-07-02 06:41:18.914                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.914             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.914         else:
2025-07-02 06:41:18.914             # the synch pair is identical
2025-07-02 06:41:18.914             yield '  ' + aelt
2025-07-02 06:41:18.914
2025-07-02 06:41:18.914         # pump out diffs from after the synch point
2025-07-02 06:41:18.914 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.914
2025-07-02 06:41:18.914 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.914 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.914
2025-07-02 06:41:18.914 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.914 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.914 alo = 480, ahi = 1101
2025-07-02 06:41:18.915 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.915 blo = 480, bhi = 1101
2025-07-02 06:41:18.915
2025-07-02 06:41:18.915     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.915         g = []
2025-07-02 06:41:18.915         if alo < ahi:
2025-07-02 06:41:18.915             if blo < bhi:
2025-07-02 06:41:18.915                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.915             else:
2025-07-02 06:41:18.915                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.915         elif blo < bhi:
2025-07-02 06:41:18.915             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.915
2025-07-02 06:41:18.915 >       yield from g
2025-07-02 06:41:18.915
2025-07-02 06:41:18.915 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.915 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.915
2025-07-02 06:41:18.915 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.915 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.916 alo = 480, ahi = 1101
2025-07-02 06:41:18.916 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.916 blo = 480, bhi = 1101
2025-07-02 06:41:18.916
2025-07-02 06:41:18.916     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.916         r"""
2025-07-02 06:41:18.916         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.916         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.916         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.916         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.916
2025-07-02 06:41:18.916         Example:
2025-07-02 06:41:18.916
2025-07-02 06:41:18.916         >>> d = Differ()
2025-07-02 06:41:18.916         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.916         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.916         >>> print(''.join(results), end="")
2025-07-02 06:41:18.916         - abcDefghiJkl
2025-07-02 06:41:18.916         + abcdefGhijkl
2025-07-02 06:41:18.917         """
2025-07-02 06:41:18.917
2025-07-02 06:41:18.917         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.917         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.917         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.917         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.917         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.917
2025-07-02 06:41:18.917         # search for the pair that matches best without being identical
2025-07-02 06:41:18.917         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.917         # on junk -- unless we have to)
2025-07-02 06:41:18.917         for j in range(blo, bhi):
2025-07-02 06:41:18.917             bj = b[j]
2025-07-02 06:41:18.917             cruncher.set_seq2(bj)
2025-07-02 06:41:18.917             for i in range(alo, ahi):
2025-07-02 06:41:18.917                 ai = a[i]
2025-07-02 06:41:18.917                 if ai == bj:
2025-07-02 06:41:18.917                     if eqi is None:
2025-07-02 06:41:18.917                         eqi, eqj = i, j
2025-07-02 06:41:18.917                     continue
2025-07-02 06:41:18.918                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.918                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.918                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.918                 # compares by a factor of 3.
2025-07-02 06:41:18.918                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.918                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.918                 # of the computation is cached by cruncher
2025-07-02 06:41:18.918                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.918                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.918                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.918                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.918         if best_ratio < cutoff:
2025-07-02 06:41:18.918             # no non-identical "pretty close" pair
2025-07-02 06:41:18.918             if eqi is None:
2025-07-02 06:41:18.918                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.918                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.918                 return
2025-07-02 06:41:18.918             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.918             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.918         else:
2025-07-02 06:41:18.919             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.919             eqi = None
2025-07-02 06:41:18.919
2025-07-02 06:41:18.919         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.919         # identical
2025-07-02 06:41:18.919
2025-07-02 06:41:18.919         # pump out diffs from before the synch point
2025-07-02 06:41:18.919         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.919
2025-07-02 06:41:18.919         # do intraline marking on the synch pair
2025-07-02 06:41:18.919         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.919         if eqi is None:
2025-07-02 06:41:18.919             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.919             atags = btags = ""
2025-07-02 06:41:18.919             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.919             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.919                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.919                 if tag == 'replace':
2025-07-02 06:41:18.919                     atags += '^' * la
2025-07-02 06:41:18.920                     btags += '^' * lb
2025-07-02 06:41:18.920                 elif tag == 'delete':
2025-07-02 06:41:18.920                     atags += '-' * la
2025-07-02 06:41:18.920                 elif tag == 'insert':
2025-07-02 06:41:18.920                     btags += '+' * lb
2025-07-02 06:41:18.920                 elif tag == 'equal':
2025-07-02 06:41:18.920                     atags += ' ' * la
2025-07-02 06:41:18.920                     btags += ' ' * lb
2025-07-02 06:41:18.920                 else:
2025-07-02 06:41:18.920                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.920             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.920         else:
2025-07-02 06:41:18.920             # the synch pair is identical
2025-07-02 06:41:18.920             yield '  ' + aelt
2025-07-02 06:41:18.920
2025-07-02 06:41:18.920         # pump out diffs from after the synch point
2025-07-02 06:41:18.920 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.920
2025-07-02 06:41:18.920 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.921 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.921
2025-07-02 06:41:18.921 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.921 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.921 alo = 481, ahi = 1101
2025-07-02 06:41:18.921 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.921 blo = 481, bhi = 1101
2025-07-02 06:41:18.921
2025-07-02 06:41:18.921     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.921         g = []
2025-07-02 06:41:18.921         if alo < ahi:
2025-07-02 06:41:18.921             if blo < bhi:
2025-07-02 06:41:18.921                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.921             else:
2025-07-02 06:41:18.921                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.921         elif blo < bhi:
2025-07-02 06:41:18.921             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.921
2025-07-02 06:41:18.921 >       yield from g
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.922 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.922 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.922 alo = 481, ahi = 1101
2025-07-02 06:41:18.922 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.922 blo = 481, bhi = 1101
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.922         r"""
2025-07-02 06:41:18.922         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.922         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.922         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.922         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922         Example:
2025-07-02 06:41:18.922
2025-07-02 06:41:18.922         >>> d = Differ()
2025-07-02 06:41:18.923         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.923         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.923         >>> print(''.join(results), end="")
2025-07-02 06:41:18.923         - abcDefghiJkl
2025-07-02 06:41:18.923         + abcdefGhijkl
2025-07-02 06:41:18.923         """
2025-07-02 06:41:18.923
2025-07-02 06:41:18.923         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.923         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.923         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.923         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.923         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.923
2025-07-02 06:41:18.923         # search for the pair that matches best without being identical
2025-07-02 06:41:18.923         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.923         # on junk -- unless we have to)
2025-07-02 06:41:18.923         for j in range(blo, bhi):
2025-07-02 06:41:18.923             bj = b[j]
2025-07-02 06:41:18.924             cruncher.set_seq2(bj)
2025-07-02 06:41:18.924             for i in range(alo, ahi):
2025-07-02 06:41:18.924                 ai = a[i]
2025-07-02 06:41:18.924                 if ai == bj:
2025-07-02 06:41:18.924                     if eqi is None:
2025-07-02 06:41:18.924                         eqi, eqj = i, j
2025-07-02 06:41:18.924                     continue
2025-07-02 06:41:18.924                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.924                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.924                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.924                 # compares by a factor of 3.
2025-07-02 06:41:18.924                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.924                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.924                 # of the computation is cached by cruncher
2025-07-02 06:41:18.924                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.924                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.924                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.924                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.924         if best_ratio < cutoff:
2025-07-02 06:41:18.924             # no non-identical "pretty close" pair
2025-07-02 06:41:18.925             if eqi is None:
2025-07-02 06:41:18.925                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.925                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.925                 return
2025-07-02 06:41:18.925             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.925             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.925         else:
2025-07-02 06:41:18.925             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.925             eqi = None
2025-07-02 06:41:18.925
2025-07-02 06:41:18.925         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.925         # identical
2025-07-02 06:41:18.925
2025-07-02 06:41:18.925         # pump out diffs from before the synch point
2025-07-02 06:41:18.925         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.925
2025-07-02 06:41:18.925         # do intraline marking on the synch pair
2025-07-02 06:41:18.925         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.925         if eqi is None:
2025-07-02 06:41:18.925             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.926             atags = btags = ""
2025-07-02 06:41:18.926             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.926             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.926                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.926                 if tag == 'replace':
2025-07-02 06:41:18.926                     atags += '^' * la
2025-07-02 06:41:18.926                     btags += '^' * lb
2025-07-02 06:41:18.926                 elif tag == 'delete':
2025-07-02 06:41:18.926                     atags += '-' * la
2025-07-02 06:41:18.926                 elif tag == 'insert':
2025-07-02 06:41:18.926                     btags += '+' * lb
2025-07-02 06:41:18.926                 elif tag == 'equal':
2025-07-02 06:41:18.926                     atags += ' ' * la
2025-07-02 06:41:18.926                     btags += ' ' * lb
2025-07-02 06:41:18.926                 else:
2025-07-02 06:41:18.926                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.926             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.926         else:
2025-07-02 06:41:18.926             # the synch pair is identical
2025-07-02 06:41:18.926             yield '  ' + aelt
2025-07-02 06:41:18.927
2025-07-02 06:41:18.927         # pump out diffs from after the synch point
2025-07-02 06:41:18.927 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.927
2025-07-02 06:41:18.927 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.927 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.927
2025-07-02 06:41:18.927 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.927 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.927 alo = 482, ahi = 1101
2025-07-02 06:41:18.927 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.927 blo = 482, bhi = 1101
2025-07-02 06:41:18.927
2025-07-02 06:41:18.927     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.927         g = []
2025-07-02 06:41:18.927         if alo < ahi:
2025-07-02 06:41:18.927             if blo < bhi:
2025-07-02 06:41:18.927                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.928             else:
2025-07-02 06:41:18.928                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.928         elif blo < bhi:
2025-07-02 06:41:18.928             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.928
2025-07-02 06:41:18.928 >       yield from g
2025-07-02 06:41:18.928
2025-07-02 06:41:18.928 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.928 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.928
2025-07-02 06:41:18.928 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.928 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.928 alo = 482, ahi = 1101
2025-07-02 06:41:18.928 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.928 blo = 482, bhi = 1101
2025-07-02 06:41:18.928
2025-07-02 06:41:18.928     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.928         r"""
2025-07-02 06:41:18.929         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.929         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.929         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.929         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.929
2025-07-02 06:41:18.929         Example:
2025-07-02 06:41:18.929
2025-07-02 06:41:18.929         >>> d = Differ()
2025-07-02 06:41:18.929         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.929         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.929         >>> print(''.join(results), end="")
2025-07-02 06:41:18.929         - abcDefghiJkl
2025-07-02 06:41:18.929         + abcdefGhijkl
2025-07-02 06:41:18.929         """
2025-07-02 06:41:18.929
2025-07-02 06:41:18.929         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.929         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.930         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.930         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.930         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.930
2025-07-02 06:41:18.930         # search for the pair that matches best without being identical
2025-07-02 06:41:18.930         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.930         # on junk -- unless we have to)
2025-07-02 06:41:18.930         for j in range(blo, bhi):
2025-07-02 06:41:18.930             bj = b[j]
2025-07-02 06:41:18.930             cruncher.set_seq2(bj)
2025-07-02 06:41:18.930             for i in range(alo, ahi):
2025-07-02 06:41:18.930                 ai = a[i]
2025-07-02 06:41:18.930                 if ai == bj:
2025-07-02 06:41:18.930                     if eqi is None:
2025-07-02 06:41:18.930                         eqi, eqj = i, j
2025-07-02 06:41:18.930                     continue
2025-07-02 06:41:18.930                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.930                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.930                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.930                 # compares by a factor of 3.
2025-07-02 06:41:18.931                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.931                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.931                 # of the computation is cached by cruncher
2025-07-02 06:41:18.931                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.931                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.931                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.931                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.931         if best_ratio < cutoff:
2025-07-02 06:41:18.931             # no non-identical "pretty close" pair
2025-07-02 06:41:18.931             if eqi is None:
2025-07-02 06:41:18.931                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.931                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.931                 return
2025-07-02 06:41:18.931             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.931             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.931         else:
2025-07-02 06:41:18.931             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.931             eqi = None
2025-07-02 06:41:18.931
2025-07-02 06:41:18.931         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.932         # identical
2025-07-02 06:41:18.932
2025-07-02 06:41:18.932         # pump out diffs from before the synch point
2025-07-02 06:41:18.932         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.932
2025-07-02 06:41:18.932         # do intraline marking on the synch pair
2025-07-02 06:41:18.932         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.932         if eqi is None:
2025-07-02 06:41:18.932             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.932             atags = btags = ""
2025-07-02 06:41:18.932             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.932             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.932                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.932                 if tag == 'replace':
2025-07-02 06:41:18.932                     atags += '^' * la
2025-07-02 06:41:18.932                     btags += '^' * lb
2025-07-02 06:41:18.932                 elif tag == 'delete':
2025-07-02 06:41:18.932                     atags += '-' * la
2025-07-02 06:41:18.932                 elif tag == 'insert':
2025-07-02 06:41:18.932                     btags += '+' * lb
2025-07-02 06:41:18.932                 elif tag == 'equal':
2025-07-02 06:41:18.933                     atags += ' ' * la
2025-07-02 06:41:18.933                     btags += ' ' * lb
2025-07-02 06:41:18.933                 else:
2025-07-02 06:41:18.933                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.933             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.933         else:
2025-07-02 06:41:18.933             # the synch pair is identical
2025-07-02 06:41:18.933             yield '  ' + aelt
2025-07-02 06:41:18.933
2025-07-02 06:41:18.933         # pump out diffs from after the synch point
2025-07-02 06:41:18.933 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.933
2025-07-02 06:41:18.933 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.933 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.933
2025-07-02 06:41:18.933 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.933 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.933 alo = 483, ahi = 1101
2025-07-02 06:41:18.933 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.933 blo = 483, bhi = 1101
2025-07-02 06:41:18.934
2025-07-02 06:41:18.934     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.934         g = []
2025-07-02 06:41:18.934         if alo < ahi:
2025-07-02 06:41:18.934             if blo < bhi:
2025-07-02 06:41:18.934                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.934             else:
2025-07-02 06:41:18.934                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.934         elif blo < bhi:
2025-07-02 06:41:18.934             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.934
2025-07-02 06:41:18.934 >       yield from g
2025-07-02 06:41:18.934
2025-07-02 06:41:18.934 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.934 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.934
2025-07-02 06:41:18.934 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.934 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.934 alo = 483, ahi = 1101
2025-07-02 06:41:18.934 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.935 blo = 483, bhi = 1101
2025-07-02 06:41:18.935
2025-07-02 06:41:18.935     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.935         r"""
2025-07-02 06:41:18.935         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.935         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.935         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.935         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.935
2025-07-02 06:41:18.935         Example:
2025-07-02 06:41:18.935
2025-07-02 06:41:18.935         >>> d = Differ()
2025-07-02 06:41:18.935         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.935         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.935         >>> print(''.join(results), end="")
2025-07-02 06:41:18.935         - abcDefghiJkl
2025-07-02 06:41:18.935         + abcdefGhijkl
2025-07-02 06:41:18.935         """
2025-07-02 06:41:18.936
2025-07-02 06:41:18.936         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.936         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.936         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.936         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.936         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.936
2025-07-02 06:41:18.936         # search for the pair that matches best without being identical
2025-07-02 06:41:18.936         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.936         # on junk -- unless we have to)
2025-07-02 06:41:18.936         for j in range(blo, bhi):
2025-07-02 06:41:18.936             bj = b[j]
2025-07-02 06:41:18.936             cruncher.set_seq2(bj)
2025-07-02 06:41:18.936             for i in range(alo, ahi):
2025-07-02 06:41:18.936                 ai = a[i]
2025-07-02 06:41:18.936                 if ai == bj:
2025-07-02 06:41:18.936                     if eqi is None:
2025-07-02 06:41:18.936                         eqi, eqj = i, j
2025-07-02 06:41:18.936                     continue
2025-07-02 06:41:18.936                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.937                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.937                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.937                 # compares by a factor of 3.
2025-07-02 06:41:18.937                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.937                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.937                 # of the computation is cached by cruncher
2025-07-02 06:41:18.937                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.937                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.937                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.937                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.937         if best_ratio < cutoff:
2025-07-02 06:41:18.937             # no non-identical "pretty close" pair
2025-07-02 06:41:18.937             if eqi is None:
2025-07-02 06:41:18.937                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.937                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.937                 return
2025-07-02 06:41:18.937             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.937             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.938         else:
2025-07-02 06:41:18.938             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.938             eqi = None
2025-07-02 06:41:18.938
2025-07-02 06:41:18.938         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.938         # identical
2025-07-02 06:41:18.938
2025-07-02 06:41:18.938         # pump out diffs from before the synch point
2025-07-02 06:41:18.938         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.938
2025-07-02 06:41:18.938         # do intraline marking on the synch pair
2025-07-02 06:41:18.938         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.938         if eqi is None:
2025-07-02 06:41:18.938             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.938             atags = btags = ""
2025-07-02 06:41:18.938             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.938             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.938                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.938                 if tag == 'replace':
2025-07-02 06:41:18.938                     atags += '^' * la
2025-07-02 06:41:18.939                     btags += '^' * lb
2025-07-02 06:41:18.939                 elif tag == 'delete':
2025-07-02 06:41:18.939                     atags += '-' * la
2025-07-02 06:41:18.939                 elif tag == 'insert':
2025-07-02 06:41:18.939                     btags += '+' * lb
2025-07-02 06:41:18.939                 elif tag == 'equal':
2025-07-02 06:41:18.939                     atags += ' ' * la
2025-07-02 06:41:18.939                     btags += ' ' * lb
2025-07-02 06:41:18.939                 else:
2025-07-02 06:41:18.939                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.939             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.939         else:
2025-07-02 06:41:18.939             # the synch pair is identical
2025-07-02 06:41:18.939             yield '  ' + aelt
2025-07-02 06:41:18.939
2025-07-02 06:41:18.939         # pump out diffs from after the synch point
2025-07-02 06:41:18.939 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.939
2025-07-02 06:41:18.939 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.939 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.940
2025-07-02 06:41:18.940 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.940 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.940 alo = 484, ahi = 1101
2025-07-02 06:41:18.940 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.940 blo = 484, bhi = 1101
2025-07-02 06:41:18.940
2025-07-02 06:41:18.940     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.940         g = []
2025-07-02 06:41:18.940         if alo < ahi:
2025-07-02 06:41:18.940             if blo < bhi:
2025-07-02 06:41:18.940                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.940             else:
2025-07-02 06:41:18.940                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.940         elif blo < bhi:
2025-07-02 06:41:18.940             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.940
2025-07-02 06:41:18.940 >       yield from g
2025-07-02 06:41:18.940
2025-07-02 06:41:18.940 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.940 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.941
2025-07-02 06:41:18.941 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.941 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.941 alo = 484, ahi = 1101
2025-07-02 06:41:18.941 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.941 blo = 484, bhi = 1101
2025-07-02 06:41:18.941
2025-07-02 06:41:18.941     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.941         r"""
2025-07-02 06:41:18.941         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.941         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.941         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.941         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.941
2025-07-02 06:41:18.941         Example:
2025-07-02 06:41:18.941
2025-07-02 06:41:18.941         >>> d = Differ()
2025-07-02 06:41:18.941         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.941         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.941         >>> print(''.join(results), end="")
2025-07-02 06:41:18.942         - abcDefghiJkl
2025-07-02 06:41:18.942         + abcdefGhijkl
2025-07-02 06:41:18.942         """
2025-07-02 06:41:18.942
2025-07-02 06:41:18.942         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.942         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.942         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.942         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.942         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.942
2025-07-02 06:41:18.942         # search for the pair that matches best without being identical
2025-07-02 06:41:18.942         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.942         # on junk -- unless we have to)
2025-07-02 06:41:18.942         for j in range(blo, bhi):
2025-07-02 06:41:18.942             bj = b[j]
2025-07-02 06:41:18.942             cruncher.set_seq2(bj)
2025-07-02 06:41:18.943             for i in range(alo, ahi):
2025-07-02 06:41:18.943                 ai = a[i]
2025-07-02 06:41:18.943                 if ai == bj:
2025-07-02 06:41:18.943                     if eqi is None:
2025-07-02 06:41:18.943                         eqi, eqj = i, j
2025-07-02 06:41:18.943                     continue
2025-07-02 06:41:18.943                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.943                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.943                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.943                 # compares by a factor of 3.
2025-07-02 06:41:18.943                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.943                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.943                 # of the computation is cached by cruncher
2025-07-02 06:41:18.943                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.943                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.943                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.943                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.943         if best_ratio < cutoff:
2025-07-02 06:41:18.943             # no non-identical "pretty close" pair
2025-07-02 06:41:18.943             if eqi is None:
2025-07-02 06:41:18.944                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.944                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.944                 return
2025-07-02 06:41:18.944             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.944             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.944         else:
2025-07-02 06:41:18.944             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.944             eqi = None
2025-07-02 06:41:18.944
2025-07-02 06:41:18.944         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.944         # identical
2025-07-02 06:41:18.944
2025-07-02 06:41:18.944         # pump out diffs from before the synch point
2025-07-02 06:41:18.944         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.944
2025-07-02 06:41:18.944         # do intraline marking on the synch pair
2025-07-02 06:41:18.944         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.944         if eqi is None:
2025-07-02 06:41:18.944             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.944             atags = btags = ""
2025-07-02 06:41:18.945             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.945             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.945                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.945                 if tag == 'replace':
2025-07-02 06:41:18.945                     atags += '^' * la
2025-07-02 06:41:18.945                     btags += '^' * lb
2025-07-02 06:41:18.945                 elif tag == 'delete':
2025-07-02 06:41:18.945                     atags += '-' * la
2025-07-02 06:41:18.945                 elif tag == 'insert':
2025-07-02 06:41:18.945                     btags += '+' * lb
2025-07-02 06:41:18.945                 elif tag == 'equal':
2025-07-02 06:41:18.945                     atags += ' ' * la
2025-07-02 06:41:18.945                     btags += ' ' * lb
2025-07-02 06:41:18.945                 else:
2025-07-02 06:41:18.945                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.945             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.945         else:
2025-07-02 06:41:18.945             # the synch pair is identical
2025-07-02 06:41:18.945             yield '  ' + aelt
2025-07-02 06:41:18.945
2025-07-02 06:41:18.946         # pump out diffs from after the synch point
2025-07-02 06:41:18.946 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.946
2025-07-02 06:41:18.946 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.946 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.946
2025-07-02 06:41:18.946 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.946 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.946 alo = 485, ahi = 1101
2025-07-02 06:41:18.946 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.946 blo = 485, bhi = 1101
2025-07-02 06:41:18.946
2025-07-02 06:41:18.946     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.946         g = []
2025-07-02 06:41:18.946         if alo < ahi:
2025-07-02 06:41:18.946             if blo < bhi:
2025-07-02 06:41:18.946                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.947             else:
2025-07-02 06:41:18.947                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.947         elif blo < bhi:
2025-07-02 06:41:18.947             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.947
2025-07-02 06:41:18.947 >       yield from g
2025-07-02 06:41:18.947
2025-07-02 06:41:18.947 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.947 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.947
2025-07-02 06:41:18.947 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.947 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.947 alo = 485, ahi = 1101
2025-07-02 06:41:18.947 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.947 blo = 485, bhi = 1101
2025-07-02 06:41:18.947
2025-07-02 06:41:18.947     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.947         r"""
2025-07-02 06:41:18.947         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.948         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.948         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.948         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.948
2025-07-02 06:41:18.948         Example:
2025-07-02 06:41:18.948
2025-07-02 06:41:18.948         >>> d = Differ()
2025-07-02 06:41:18.948         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.948         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.948         >>> print(''.join(results), end="")
2025-07-02 06:41:18.948         - abcDefghiJkl
2025-07-02 06:41:18.948         + abcdefGhijkl
2025-07-02 06:41:18.948         """
2025-07-02 06:41:18.948
2025-07-02 06:41:18.948         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.948         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.948         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.948         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.949         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.949
2025-07-02 06:41:18.949         # search for the pair that matches best without being identical
2025-07-02 06:41:18.949         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.949         # on junk -- unless we have to)
2025-07-02 06:41:18.949         for j in range(blo, bhi):
2025-07-02 06:41:18.949             bj = b[j]
2025-07-02 06:41:18.949             cruncher.set_seq2(bj)
2025-07-02 06:41:18.949             for i in range(alo, ahi):
2025-07-02 06:41:18.949                 ai = a[i]
2025-07-02 06:41:18.949                 if ai == bj:
2025-07-02 06:41:18.949                     if eqi is None:
2025-07-02 06:41:18.949                         eqi, eqj = i, j
2025-07-02 06:41:18.949                     continue
2025-07-02 06:41:18.949                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.949                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.949                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.949                 # compares by a factor of 3.
2025-07-02 06:41:18.949                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.949                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.950                 # of the computation is cached by cruncher
2025-07-02 06:41:18.950                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.950                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.950                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.950                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.950         if best_ratio < cutoff:
2025-07-02 06:41:18.950             # no non-identical "pretty close" pair
2025-07-02 06:41:18.950             if eqi is None:
2025-07-02 06:41:18.950                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.950                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.950                 return
2025-07-02 06:41:18.950             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.950             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.950         else:
2025-07-02 06:41:18.950             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.950             eqi = None
2025-07-02 06:41:18.950
2025-07-02 06:41:18.950         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.950         # identical
2025-07-02 06:41:18.950
2025-07-02 06:41:18.950         # pump out diffs from before the synch point
2025-07-02 06:41:18.951         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.951
2025-07-02 06:41:18.951         # do intraline marking on the synch pair
2025-07-02 06:41:18.951         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.951         if eqi is None:
2025-07-02 06:41:18.951             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.951             atags = btags = ""
2025-07-02 06:41:18.951             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.951             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.951                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.951                 if tag == 'replace':
2025-07-02 06:41:18.951                     atags += '^' * la
2025-07-02 06:41:18.951                     btags += '^' * lb
2025-07-02 06:41:18.951                 elif tag == 'delete':
2025-07-02 06:41:18.951                     atags += '-' * la
2025-07-02 06:41:18.951                 elif tag == 'insert':
2025-07-02 06:41:18.951                     btags += '+' * lb
2025-07-02 06:41:18.951                 elif tag == 'equal':
2025-07-02 06:41:18.951                     atags += ' ' * la
2025-07-02 06:41:18.951                     btags += ' ' * lb
2025-07-02 06:41:18.952                 else:
2025-07-02 06:41:18.952                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.952             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.952         else:
2025-07-02 06:41:18.952             # the synch pair is identical
2025-07-02 06:41:18.952             yield '  ' + aelt
2025-07-02 06:41:18.952
2025-07-02 06:41:18.952         # pump out diffs from after the synch point
2025-07-02 06:41:18.952 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.952
2025-07-02 06:41:18.952 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.952 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.952
2025-07-02 06:41:18.952 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.952 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.952 alo = 488, ahi = 1101
2025-07-02 06:41:18.952 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.952 blo = 488, bhi = 1101
2025-07-02 06:41:18.952
2025-07-02 06:41:18.952     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.953         g = []
2025-07-02 06:41:18.953         if alo < ahi:
2025-07-02 06:41:18.953             if blo < bhi:
2025-07-02 06:41:18.953                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.953             else:
2025-07-02 06:41:18.953                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.953         elif blo < bhi:
2025-07-02 06:41:18.953             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.953
2025-07-02 06:41:18.953 >       yield from g
2025-07-02 06:41:18.953
2025-07-02 06:41:18.953 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.953 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.953
2025-07-02 06:41:18.953 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.953 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.953 alo = 488, ahi = 1101
2025-07-02 06:41:18.953 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.953 blo = 488, bhi = 1101
2025-07-02 06:41:18.953
2025-07-02 06:41:18.954     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.954         r"""
2025-07-02 06:41:18.954         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.954         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.954         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.954         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.954
2025-07-02 06:41:18.954         Example:
2025-07-02 06:41:18.954
2025-07-02 06:41:18.954         >>> d = Differ()
2025-07-02 06:41:18.954         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.954         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.954         >>> print(''.join(results), end="")
2025-07-02 06:41:18.954         - abcDefghiJkl
2025-07-02 06:41:18.954         + abcdefGhijkl
2025-07-02 06:41:18.954         """
2025-07-02 06:41:18.955
2025-07-02 06:41:18.955         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.955         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.955         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.955         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.955         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.955
2025-07-02 06:41:18.955         # search for the pair that matches best without being identical
2025-07-02 06:41:18.955         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.955         # on junk -- unless we have to)
2025-07-02 06:41:18.955         for j in range(blo, bhi):
2025-07-02 06:41:18.955             bj = b[j]
2025-07-02 06:41:18.955             cruncher.set_seq2(bj)
2025-07-02 06:41:18.955             for i in range(alo, ahi):
2025-07-02 06:41:18.955                 ai = a[i]
2025-07-02 06:41:18.955                 if ai == bj:
2025-07-02 06:41:18.955                     if eqi is None:
2025-07-02 06:41:18.955                         eqi, eqj = i, j
2025-07-02 06:41:18.955                     continue
2025-07-02 06:41:18.955                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.956                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.956                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.956                 # compares by a factor of 3.
2025-07-02 06:41:18.956                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.956                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.956                 # of the computation is cached by cruncher
2025-07-02 06:41:18.956                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.956                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.956                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.956                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.956         if best_ratio < cutoff:
2025-07-02 06:41:18.956             # no non-identical "pretty close" pair
2025-07-02 06:41:18.956             if eqi is None:
2025-07-02 06:41:18.956                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.956                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.956                 return
2025-07-02 06:41:18.956             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.956             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.956         else:
2025-07-02 06:41:18.957             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.957             eqi = None
2025-07-02 06:41:18.957
2025-07-02 06:41:18.957         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.957         # identical
2025-07-02 06:41:18.957
2025-07-02 06:41:18.957         # pump out diffs from before the synch point
2025-07-02 06:41:18.957         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.957
2025-07-02 06:41:18.957         # do intraline marking on the synch pair
2025-07-02 06:41:18.957         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.957         if eqi is None:
2025-07-02 06:41:18.957             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.957             atags = btags = ""
2025-07-02 06:41:18.957             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.957             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.957                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.957                 if tag == 'replace':
2025-07-02 06:41:18.957                     atags += '^' * la
2025-07-02 06:41:18.957                     btags += '^' * lb
2025-07-02 06:41:18.957                 elif tag == 'delete':
2025-07-02 06:41:18.958                     atags += '-' * la
2025-07-02 06:41:18.958                 elif tag == 'insert':
2025-07-02 06:41:18.958                     btags += '+' * lb
2025-07-02 06:41:18.958                 elif tag == 'equal':
2025-07-02 06:41:18.958                     atags += ' ' * la
2025-07-02 06:41:18.958                     btags += ' ' * lb
2025-07-02 06:41:18.958                 else:
2025-07-02 06:41:18.958                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.958             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.958         else:
2025-07-02 06:41:18.958             # the synch pair is identical
2025-07-02 06:41:18.958             yield '  ' + aelt
2025-07-02 06:41:18.958
2025-07-02 06:41:18.958         # pump out diffs from after the synch point
2025-07-02 06:41:18.958 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.958
2025-07-02 06:41:18.958 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.959 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.959
2025-07-02 06:41:18.959 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.959 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.959 alo = 489, ahi = 1101
2025-07-02 06:41:18.959 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.959 blo = 489, bhi = 1101
2025-07-02 06:41:18.959
2025-07-02 06:41:18.959     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.959         g = []
2025-07-02 06:41:18.959         if alo < ahi:
2025-07-02 06:41:18.959             if blo < bhi:
2025-07-02 06:41:18.959                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.959             else:
2025-07-02 06:41:18.959                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.959         elif blo < bhi:
2025-07-02 06:41:18.959             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.959
2025-07-02 06:41:18.959 >       yield from g
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.960 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.960 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.960 alo = 489, ahi = 1101
2025-07-02 06:41:18.960 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.960 blo = 489, bhi = 1101
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.960         r"""
2025-07-02 06:41:18.960         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.960         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.960         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.960         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960         Example:
2025-07-02 06:41:18.960
2025-07-02 06:41:18.960         >>> d = Differ()
2025-07-02 06:41:18.961         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.961         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.961         >>> print(''.join(results), end="")
2025-07-02 06:41:18.961         - abcDefghiJkl
2025-07-02 06:41:18.961         + abcdefGhijkl
2025-07-02 06:41:18.961         """
2025-07-02 06:41:18.961
2025-07-02 06:41:18.961         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.961         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.961         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.961         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.961         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.961
2025-07-02 06:41:18.961         # search for the pair that matches best without being identical
2025-07-02 06:41:18.961         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.961         # on junk -- unless we have to)
2025-07-02 06:41:18.961         for j in range(blo, bhi):
2025-07-02 06:41:18.962             bj = b[j]
2025-07-02 06:41:18.962             cruncher.set_seq2(bj)
2025-07-02 06:41:18.962             for i in range(alo, ahi):
2025-07-02 06:41:18.962                 ai = a[i]
2025-07-02 06:41:18.962                 if ai == bj:
2025-07-02 06:41:18.962                     if eqi is None:
2025-07-02 06:41:18.962                         eqi, eqj = i, j
2025-07-02 06:41:18.962                     continue
2025-07-02 06:41:18.962                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.962                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.962                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.962                 # compares by a factor of 3.
2025-07-02 06:41:18.962                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.962                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.962                 # of the computation is cached by cruncher
2025-07-02 06:41:18.962                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.962                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.962                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.962                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.962         if best_ratio < cutoff:
2025-07-02 06:41:18.963             # no non-identical "pretty close" pair
2025-07-02 06:41:18.963             if eqi is None:
2025-07-02 06:41:18.963                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.963                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.963                 return
2025-07-02 06:41:18.963             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.963             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.963         else:
2025-07-02 06:41:18.963             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.963             eqi = None
2025-07-02 06:41:18.963
2025-07-02 06:41:18.963         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.963         # identical
2025-07-02 06:41:18.963
2025-07-02 06:41:18.963         # pump out diffs from before the synch point
2025-07-02 06:41:18.963         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.963
2025-07-02 06:41:18.964         # do intraline marking on the synch pair
2025-07-02 06:41:18.964         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.964         if eqi is None:
2025-07-02 06:41:18.964             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.964             atags = btags = ""
2025-07-02 06:41:18.964             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.964             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.964                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.964                 if tag == 'replace':
2025-07-02 06:41:18.964                     atags += '^' * la
2025-07-02 06:41:18.964                     btags += '^' * lb
2025-07-02 06:41:18.964                 elif tag == 'delete':
2025-07-02 06:41:18.964                     atags += '-' * la
2025-07-02 06:41:18.964                 elif tag == 'insert':
2025-07-02 06:41:18.964                     btags += '+' * lb
2025-07-02 06:41:18.964                 elif tag == 'equal':
2025-07-02 06:41:18.964                     atags += ' ' * la
2025-07-02 06:41:18.964                     btags += ' ' * lb
2025-07-02 06:41:18.964                 else:
2025-07-02 06:41:18.965                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.965             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.965         else:
2025-07-02 06:41:18.965             # the synch pair is identical
2025-07-02 06:41:18.965             yield '  ' + aelt
2025-07-02 06:41:18.965
2025-07-02 06:41:18.965         # pump out diffs from after the synch point
2025-07-02 06:41:18.965 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.965
2025-07-02 06:41:18.965 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.965 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.965
2025-07-02 06:41:18.965 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.965 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.965 alo = 490, ahi = 1101
2025-07-02 06:41:18.965 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.965 blo = 490, bhi = 1101
2025-07-02 06:41:18.965
2025-07-02 06:41:18.965     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.966         g = []
2025-07-02 06:41:18.966         if alo < ahi:
2025-07-02 06:41:18.966             if blo < bhi:
2025-07-02 06:41:18.966                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.966             else:
2025-07-02 06:41:18.966                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.966         elif blo < bhi:
2025-07-02 06:41:18.966             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.966
2025-07-02 06:41:18.966 >       yield from g
2025-07-02 06:41:18.966
2025-07-02 06:41:18.966 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.966 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.966
2025-07-02 06:41:18.966 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.966 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.966 alo = 490, ahi = 1101
2025-07-02 06:41:18.966 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.966 blo = 490, bhi = 1101
2025-07-02 06:41:18.967
2025-07-02 06:41:18.967     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.967         r"""
2025-07-02 06:41:18.967         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.967         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.967         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.967         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.967
2025-07-02 06:41:18.967         Example:
2025-07-02 06:41:18.967
2025-07-02 06:41:18.967         >>> d = Differ()
2025-07-02 06:41:18.967         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.967         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.967         >>> print(''.join(results), end="")
2025-07-02 06:41:18.967         - abcDefghiJkl
2025-07-02 06:41:18.967         + abcdefGhijkl
2025-07-02 06:41:18.967         """
2025-07-02 06:41:18.967
2025-07-02 06:41:18.968         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.968         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.968         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.968         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.968         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.968
2025-07-02 06:41:18.968         # search for the pair that matches best without being identical
2025-07-02 06:41:18.968         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.968         # on junk -- unless we have to)
2025-07-02 06:41:18.968         for j in range(blo, bhi):
2025-07-02 06:41:18.968             bj = b[j]
2025-07-02 06:41:18.968             cruncher.set_seq2(bj)
2025-07-02 06:41:18.968             for i in range(alo, ahi):
2025-07-02 06:41:18.968                 ai = a[i]
2025-07-02 06:41:18.968                 if ai == bj:
2025-07-02 06:41:18.968                     if eqi is None:
2025-07-02 06:41:18.968                         eqi, eqj = i, j
2025-07-02 06:41:18.968                     continue
2025-07-02 06:41:18.968                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.969                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.969                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.969                 # compares by a factor of 3.
2025-07-02 06:41:18.969                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.969                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.969                 # of the computation is cached by cruncher
2025-07-02 06:41:18.969                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.969                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.969                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.969                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.969         if best_ratio < cutoff:
2025-07-02 06:41:18.969             # no non-identical "pretty close" pair
2025-07-02 06:41:18.969             if eqi is None:
2025-07-02 06:41:18.969                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.969                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.969                 return
2025-07-02 06:41:18.969             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.969             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.969         else:
2025-07-02 06:41:18.969             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.970             eqi = None
2025-07-02 06:41:18.970
2025-07-02 06:41:18.970         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.970         # identical
2025-07-02 06:41:18.970
2025-07-02 06:41:18.970         # pump out diffs from before the synch point
2025-07-02 06:41:18.970         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.970
2025-07-02 06:41:18.970         # do intraline marking on the synch pair
2025-07-02 06:41:18.970         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.970         if eqi is None:
2025-07-02 06:41:18.970             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.970             atags = btags = ""
2025-07-02 06:41:18.970             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.970             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.970                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.970                 if tag == 'replace':
2025-07-02 06:41:18.970                     atags += '^' * la
2025-07-02 06:41:18.970                     btags += '^' * lb
2025-07-02 06:41:18.971                 elif tag == 'delete':
2025-07-02 06:41:18.971                     atags += '-' * la
2025-07-02 06:41:18.971                 elif tag == 'insert':
2025-07-02 06:41:18.971                     btags += '+' * lb
2025-07-02 06:41:18.971                 elif tag == 'equal':
2025-07-02 06:41:18.971                     atags += ' ' * la
2025-07-02 06:41:18.971                     btags += ' ' * lb
2025-07-02 06:41:18.971                 else:
2025-07-02 06:41:18.971                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.971             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.971         else:
2025-07-02 06:41:18.971             # the synch pair is identical
2025-07-02 06:41:18.971             yield '  ' + aelt
2025-07-02 06:41:18.971
2025-07-02 06:41:18.971         # pump out diffs from after the synch point
2025-07-02 06:41:18.971 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.971
2025-07-02 06:41:18.971 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.971 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.971
2025-07-02 06:41:18.972 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.972 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.972 alo = 491, ahi = 1101
2025-07-02 06:41:18.972 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.972 blo = 491, bhi = 1101
2025-07-02 06:41:18.972
2025-07-02 06:41:18.972     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.972         g = []
2025-07-02 06:41:18.972         if alo < ahi:
2025-07-02 06:41:18.972             if blo < bhi:
2025-07-02 06:41:18.972                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.972             else:
2025-07-02 06:41:18.972                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.972         elif blo < bhi:
2025-07-02 06:41:18.972             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.972
2025-07-02 06:41:18.972 >       yield from g
2025-07-02 06:41:18.972
2025-07-02 06:41:18.973 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.973 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.973
2025-07-02 06:41:18.973 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.973 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.973 alo = 491, ahi = 1101
2025-07-02 06:41:18.973 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.973 blo = 491, bhi = 1101
2025-07-02 06:41:18.973
2025-07-02 06:41:18.973     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.973         r"""
2025-07-02 06:41:18.973         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.973         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.973         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.973         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.973
2025-07-02 06:41:18.973         Example:
2025-07-02 06:41:18.973
2025-07-02 06:41:18.974         >>> d = Differ()
2025-07-02 06:41:18.974         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.974         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.974         >>> print(''.join(results), end="")
2025-07-02 06:41:18.974         - abcDefghiJkl
2025-07-02 06:41:18.974         + abcdefGhijkl
2025-07-02 06:41:18.974         """
2025-07-02 06:41:18.974
2025-07-02 06:41:18.974         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.974         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.974         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.974         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.974         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.974
2025-07-02 06:41:18.974         # search for the pair that matches best without being identical
2025-07-02 06:41:18.974         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.974         # on junk -- unless we have to)
2025-07-02 06:41:18.975         for j in range(blo, bhi):
2025-07-02 06:41:18.975             bj = b[j]
2025-07-02 06:41:18.975             cruncher.set_seq2(bj)
2025-07-02 06:41:18.975             for i in range(alo, ahi):
2025-07-02 06:41:18.975                 ai = a[i]
2025-07-02 06:41:18.975                 if ai == bj:
2025-07-02 06:41:18.975                     if eqi is None:
2025-07-02 06:41:18.975                         eqi, eqj = i, j
2025-07-02 06:41:18.975                     continue
2025-07-02 06:41:18.975                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.975                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.975                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.975                 # compares by a factor of 3.
2025-07-02 06:41:18.975                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.975                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.975                 # of the computation is cached by cruncher
2025-07-02 06:41:18.975                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.975                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.975                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.975                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.976         if best_ratio < cutoff:
2025-07-02 06:41:18.976             # no non-identical "pretty close" pair
2025-07-02 06:41:18.976             if eqi is None:
2025-07-02 06:41:18.976                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.976                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.976                 return
2025-07-02 06:41:18.976             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.976             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.976         else:
2025-07-02 06:41:18.976             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.976             eqi = None
2025-07-02 06:41:18.976
2025-07-02 06:41:18.976         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.976         # identical
2025-07-02 06:41:18.976
2025-07-02 06:41:18.976         # pump out diffs from before the synch point
2025-07-02 06:41:18.976         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.976
2025-07-02 06:41:18.976         # do intraline marking on the synch pair
2025-07-02 06:41:18.977         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.977         if eqi is None:
2025-07-02 06:41:18.977             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.977             atags = btags = ""
2025-07-02 06:41:18.977             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.977             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.977                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.977                 if tag == 'replace':
2025-07-02 06:41:18.977                     atags += '^' * la
2025-07-02 06:41:18.977                     btags += '^' * lb
2025-07-02 06:41:18.977                 elif tag == 'delete':
2025-07-02 06:41:18.977                     atags += '-' * la
2025-07-02 06:41:18.977                 elif tag == 'insert':
2025-07-02 06:41:18.977                     btags += '+' * lb
2025-07-02 06:41:18.977                 elif tag == 'equal':
2025-07-02 06:41:18.977                     atags += ' ' * la
2025-07-02 06:41:18.977                     btags += ' ' * lb
2025-07-02 06:41:18.977                 else:
2025-07-02 06:41:18.977                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.977             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.978         else:
2025-07-02 06:41:18.978             # the synch pair is identical
2025-07-02 06:41:18.978             yield '  ' + aelt
2025-07-02 06:41:18.978
2025-07-02 06:41:18.978         # pump out diffs from after the synch point
2025-07-02 06:41:18.978 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.978
2025-07-02 06:41:18.978 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.978 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.978
2025-07-02 06:41:18.978 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.978 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.978 alo = 492, ahi = 1101
2025-07-02 06:41:18.978 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.978 blo = 492, bhi = 1101
2025-07-02 06:41:18.978
2025-07-02 06:41:18.978     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.978         g = []
2025-07-02 06:41:18.978         if alo < ahi:
2025-07-02 06:41:18.979             if blo < bhi:
2025-07-02 06:41:18.979                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.979             else:
2025-07-02 06:41:18.979                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.979         elif blo < bhi:
2025-07-02 06:41:18.979             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.979
2025-07-02 06:41:18.979 >       yield from g
2025-07-02 06:41:18.979
2025-07-02 06:41:18.979 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.979 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.979
2025-07-02 06:41:18.979 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.979 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.979 alo = 492, ahi = 1101
2025-07-02 06:41:18.979 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.979 blo = 492, bhi = 1101
2025-07-02 06:41:18.979
2025-07-02 06:41:18.979     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.979         r"""
2025-07-02 06:41:18.980         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.980         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.980         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.980         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.980
2025-07-02 06:41:18.980         Example:
2025-07-02 06:41:18.980
2025-07-02 06:41:18.980         >>> d = Differ()
2025-07-02 06:41:18.980         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.980         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.980         >>> print(''.join(results), end="")
2025-07-02 06:41:18.980         - abcDefghiJkl
2025-07-02 06:41:18.980         + abcdefGhijkl
2025-07-02 06:41:18.980         """
2025-07-02 06:41:18.980
2025-07-02 06:41:18.980         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.980         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.981         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.981         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.981         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.981
2025-07-02 06:41:18.981         # search for the pair that matches best without being identical
2025-07-02 06:41:18.981         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.981         # on junk -- unless we have to)
2025-07-02 06:41:18.981         for j in range(blo, bhi):
2025-07-02 06:41:18.981             bj = b[j]
2025-07-02 06:41:18.981             cruncher.set_seq2(bj)
2025-07-02 06:41:18.981             for i in range(alo, ahi):
2025-07-02 06:41:18.981                 ai = a[i]
2025-07-02 06:41:18.981                 if ai == bj:
2025-07-02 06:41:18.981                     if eqi is None:
2025-07-02 06:41:18.981                         eqi, eqj = i, j
2025-07-02 06:41:18.981                     continue
2025-07-02 06:41:18.981                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.981                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.981                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.982                 # compares by a factor of 3.
2025-07-02 06:41:18.982                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.982                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.982                 # of the computation is cached by cruncher
2025-07-02 06:41:18.982                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.982                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.982                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.982                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.982         if best_ratio < cutoff:
2025-07-02 06:41:18.982             # no non-identical "pretty close" pair
2025-07-02 06:41:18.982             if eqi is None:
2025-07-02 06:41:18.982                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.982                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.982                 return
2025-07-02 06:41:18.982             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.982             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.982         else:
2025-07-02 06:41:18.982             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.982             eqi = None
2025-07-02 06:41:18.983
2025-07-02 06:41:18.983         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.983         # identical
2025-07-02 06:41:18.983
2025-07-02 06:41:18.983         # pump out diffs from before the synch point
2025-07-02 06:41:18.983         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.983
2025-07-02 06:41:18.983         # do intraline marking on the synch pair
2025-07-02 06:41:18.983         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.983         if eqi is None:
2025-07-02 06:41:18.983             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.983             atags = btags = ""
2025-07-02 06:41:18.983             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.983             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.983                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.983                 if tag == 'replace':
2025-07-02 06:41:18.983                     atags += '^' * la
2025-07-02 06:41:18.983                     btags += '^' * lb
2025-07-02 06:41:18.983                 elif tag == 'delete':
2025-07-02 06:41:18.984                     atags += '-' * la
2025-07-02 06:41:18.984                 elif tag == 'insert':
2025-07-02 06:41:18.984                     btags += '+' * lb
2025-07-02 06:41:18.984                 elif tag == 'equal':
2025-07-02 06:41:18.984                     atags += ' ' * la
2025-07-02 06:41:18.984                     btags += ' ' * lb
2025-07-02 06:41:18.984                 else:
2025-07-02 06:41:18.984                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.984             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.984         else:
2025-07-02 06:41:18.984             # the synch pair is identical
2025-07-02 06:41:18.984             yield '  ' + aelt
2025-07-02 06:41:18.984
2025-07-02 06:41:18.984         # pump out diffs from after the synch point
2025-07-02 06:41:18.984 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.984
2025-07-02 06:41:18.984 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.984 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.984
2025-07-02 06:41:18.984 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.985 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.985 alo = 493, ahi = 1101
2025-07-02 06:41:18.985 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.985 blo = 493, bhi = 1101
2025-07-02 06:41:18.985
2025-07-02 06:41:18.985     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.985         g = []
2025-07-02 06:41:18.985         if alo < ahi:
2025-07-02 06:41:18.985             if blo < bhi:
2025-07-02 06:41:18.985                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.985             else:
2025-07-02 06:41:18.985                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.985         elif blo < bhi:
2025-07-02 06:41:18.985             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.985
2025-07-02 06:41:18.985 >       yield from g
2025-07-02 06:41:18.985
2025-07-02 06:41:18.985 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.986 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.986
2025-07-02 06:41:18.986 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.986 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.986 alo = 493, ahi = 1101
2025-07-02 06:41:18.986 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.986 blo = 493, bhi = 1101
2025-07-02 06:41:18.986
2025-07-02 06:41:18.986     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.986         r"""
2025-07-02 06:41:18.986         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.986         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.986         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.986         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.986
2025-07-02 06:41:18.986         Example:
2025-07-02 06:41:18.986
2025-07-02 06:41:18.986         >>> d = Differ()
2025-07-02 06:41:18.986         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.987         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.987         >>> print(''.join(results), end="")
2025-07-02 06:41:18.987         - abcDefghiJkl
2025-07-02 06:41:18.987         + abcdefGhijkl
2025-07-02 06:41:18.987         """
2025-07-02 06:41:18.987
2025-07-02 06:41:18.987         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.987         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.987         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.987         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.987         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.987
2025-07-02 06:41:18.987         # search for the pair that matches best without being identical
2025-07-02 06:41:18.987         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.987         # on junk -- unless we have to)
2025-07-02 06:41:18.987         for j in range(blo, bhi):
2025-07-02 06:41:18.987             bj = b[j]
2025-07-02 06:41:18.988             cruncher.set_seq2(bj)
2025-07-02 06:41:18.988             for i in range(alo, ahi):
2025-07-02 06:41:18.988                 ai = a[i]
2025-07-02 06:41:18.988                 if ai == bj:
2025-07-02 06:41:18.988                     if eqi is None:
2025-07-02 06:41:18.988                         eqi, eqj = i, j
2025-07-02 06:41:18.988                     continue
2025-07-02 06:41:18.988                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.988                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.988                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.988                 # compares by a factor of 3.
2025-07-02 06:41:18.988                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.988                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.988                 # of the computation is cached by cruncher
2025-07-02 06:41:18.988                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.988                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.988                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.988                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.988         if best_ratio < cutoff:
2025-07-02 06:41:18.988             # no non-identical "pretty close" pair
2025-07-02 06:41:18.989             if eqi is None:
2025-07-02 06:41:18.989                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.989                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.989                 return
2025-07-02 06:41:18.989             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.989             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.989         else:
2025-07-02 06:41:18.989             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.989             eqi = None
2025-07-02 06:41:18.989
2025-07-02 06:41:18.989         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.989         # identical
2025-07-02 06:41:18.989
2025-07-02 06:41:18.989         # pump out diffs from before the synch point
2025-07-02 06:41:18.989         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.989
2025-07-02 06:41:18.989         # do intraline marking on the synch pair
2025-07-02 06:41:18.990         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.990         if eqi is None:
2025-07-02 06:41:18.990             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.990             atags = btags = ""
2025-07-02 06:41:18.990             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.990             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.990                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.990                 if tag == 'replace':
2025-07-02 06:41:18.990                     atags += '^' * la
2025-07-02 06:41:18.990                     btags += '^' * lb
2025-07-02 06:41:18.990                 elif tag == 'delete':
2025-07-02 06:41:18.990                     atags += '-' * la
2025-07-02 06:41:18.990                 elif tag == 'insert':
2025-07-02 06:41:18.990                     btags += '+' * lb
2025-07-02 06:41:18.990                 elif tag == 'equal':
2025-07-02 06:41:18.990                     atags += ' ' * la
2025-07-02 06:41:18.990                     btags += ' ' * lb
2025-07-02 06:41:18.990                 else:
2025-07-02 06:41:18.991                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.991             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.991         else:
2025-07-02 06:41:18.991             # the synch pair is identical
2025-07-02 06:41:18.991             yield '  ' + aelt
2025-07-02 06:41:18.991
2025-07-02 06:41:18.991         # pump out diffs from after the synch point
2025-07-02 06:41:18.991 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.991
2025-07-02 06:41:18.991 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.991 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.991
2025-07-02 06:41:18.991 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.991 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.991 alo = 494, ahi = 1101
2025-07-02 06:41:18.991 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.991 blo = 494, bhi = 1101
2025-07-02 06:41:18.991
2025-07-02 06:41:18.992     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.992         g = []
2025-07-02 06:41:18.992         if alo < ahi:
2025-07-02 06:41:18.992             if blo < bhi:
2025-07-02 06:41:18.992                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.992             else:
2025-07-02 06:41:18.992                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.992         elif blo < bhi:
2025-07-02 06:41:18.992             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.992
2025-07-02 06:41:18.992 >       yield from g
2025-07-02 06:41:18.992
2025-07-02 06:41:18.992 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.992 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.992
2025-07-02 06:41:18.992 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.992 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.992 alo = 494, ahi = 1101
2025-07-02 06:41:18.993 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.993 blo = 494, bhi = 1101
2025-07-02 06:41:18.993
2025-07-02 06:41:18.993     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.993         r"""
2025-07-02 06:41:18.993         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:18.993         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:18.993         synch point, and intraline difference marking is done on the
2025-07-02 06:41:18.993         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:18.993
2025-07-02 06:41:18.993         Example:
2025-07-02 06:41:18.993
2025-07-02 06:41:18.993         >>> d = Differ()
2025-07-02 06:41:18.993         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:18.993         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:18.993         >>> print(''.join(results), end="")
2025-07-02 06:41:18.993         - abcDefghiJkl
2025-07-02 06:41:18.993         + abcdefGhijkl
2025-07-02 06:41:18.994         """
2025-07-02 06:41:18.994
2025-07-02 06:41:18.994         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:18.994         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:18.994         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:18.994         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:18.994         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:18.994
2025-07-02 06:41:18.994         # search for the pair that matches best without being identical
2025-07-02 06:41:18.994         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:18.994         # on junk -- unless we have to)
2025-07-02 06:41:18.994         for j in range(blo, bhi):
2025-07-02 06:41:18.994             bj = b[j]
2025-07-02 06:41:18.994             cruncher.set_seq2(bj)
2025-07-02 06:41:18.994             for i in range(alo, ahi):
2025-07-02 06:41:18.994                 ai = a[i]
2025-07-02 06:41:18.994                 if ai == bj:
2025-07-02 06:41:18.995                     if eqi is None:
2025-07-02 06:41:18.995                         eqi, eqj = i, j
2025-07-02 06:41:18.995                     continue
2025-07-02 06:41:18.995                 cruncher.set_seq1(ai)
2025-07-02 06:41:18.995                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:18.995                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:18.995                 # compares by a factor of 3.
2025-07-02 06:41:18.995                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:18.995                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:18.995                 # of the computation is cached by cruncher
2025-07-02 06:41:18.995                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:18.995                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:18.995                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:18.995                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:18.995         if best_ratio < cutoff:
2025-07-02 06:41:18.995             # no non-identical "pretty close" pair
2025-07-02 06:41:18.995             if eqi is None:
2025-07-02 06:41:18.995                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:18.996                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.996                 return
2025-07-02 06:41:18.996             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:18.996             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:18.996         else:
2025-07-02 06:41:18.996             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:18.996             eqi = None
2025-07-02 06:41:18.996
2025-07-02 06:41:18.996         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:18.996         # identical
2025-07-02 06:41:18.996
2025-07-02 06:41:18.996         # pump out diffs from before the synch point
2025-07-02 06:41:18.996         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:18.996
2025-07-02 06:41:18.996         # do intraline marking on the synch pair
2025-07-02 06:41:18.996         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:18.996         if eqi is None:
2025-07-02 06:41:18.996             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:18.996             atags = btags = ""
2025-07-02 06:41:18.997             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:18.997             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:18.997                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:18.997                 if tag == 'replace':
2025-07-02 06:41:18.997                     atags += '^' * la
2025-07-02 06:41:18.997                     btags += '^' * lb
2025-07-02 06:41:18.997                 elif tag == 'delete':
2025-07-02 06:41:18.997                     atags += '-' * la
2025-07-02 06:41:18.997                 elif tag == 'insert':
2025-07-02 06:41:18.997                     btags += '+' * lb
2025-07-02 06:41:18.997                 elif tag == 'equal':
2025-07-02 06:41:18.997                     atags += ' ' * la
2025-07-02 06:41:18.997                     btags += ' ' * lb
2025-07-02 06:41:18.997                 else:
2025-07-02 06:41:18.997                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:18.997             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:18.997         else:
2025-07-02 06:41:18.997             # the synch pair is identical
2025-07-02 06:41:18.997             yield '  ' + aelt
2025-07-02 06:41:18.998
2025-07-02 06:41:18.998         # pump out diffs from after the synch point
2025-07-02 06:41:18.998 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:18.998
2025-07-02 06:41:18.998 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:18.998 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.998
2025-07-02 06:41:18.998 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.998 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.998 alo = 495, ahi = 1101
2025-07-02 06:41:18.998 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.998 blo = 495, bhi = 1101
2025-07-02 06:41:18.998
2025-07-02 06:41:18.998     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.998         g = []
2025-07-02 06:41:18.998         if alo < ahi:
2025-07-02 06:41:18.998             if blo < bhi:
2025-07-02 06:41:18.998                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:18.998             else:
2025-07-02 06:41:18.999                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:18.999         elif blo < bhi:
2025-07-02 06:41:18.999             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:18.999
2025-07-02 06:41:18.999 >       yield from g
2025-07-02 06:41:18.999
2025-07-02 06:41:18.999 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:18.999 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:18.999
2025-07-02 06:41:18.999 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:18.999 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:18.999 alo = 495, ahi = 1101
2025-07-02 06:41:18.999 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:18.999 blo = 495, bhi = 1101
2025-07-02 06:41:18.999
2025-07-02 06:41:18.999     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:18.999         r"""
2025-07-02 06:41:19.000         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.000         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.000         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.000         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.000
2025-07-02 06:41:19.000         Example:
2025-07-02 06:41:19.000
2025-07-02 06:41:19.000         >>> d = Differ()
2025-07-02 06:41:19.000         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.000         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.000         >>> print(''.join(results), end="")
2025-07-02 06:41:19.000         - abcDefghiJkl
2025-07-02 06:41:19.000         + abcdefGhijkl
2025-07-02 06:41:19.000         """
2025-07-02 06:41:19.000
2025-07-02 06:41:19.000         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.000         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.001         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.001         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.001         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.001
2025-07-02 06:41:19.001         # search for the pair that matches best without being identical
2025-07-02 06:41:19.001         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.001         # on junk -- unless we have to)
2025-07-02 06:41:19.001         for j in range(blo, bhi):
2025-07-02 06:41:19.001             bj = b[j]
2025-07-02 06:41:19.001             cruncher.set_seq2(bj)
2025-07-02 06:41:19.001             for i in range(alo, ahi):
2025-07-02 06:41:19.001                 ai = a[i]
2025-07-02 06:41:19.001                 if ai == bj:
2025-07-02 06:41:19.001                     if eqi is None:
2025-07-02 06:41:19.001                         eqi, eqj = i, j
2025-07-02 06:41:19.001                     continue
2025-07-02 06:41:19.001                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.001                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.001                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.002                 # compares by a factor of 3.
2025-07-02 06:41:19.002                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.002                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.002                 # of the computation is cached by cruncher
2025-07-02 06:41:19.002                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.002                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.002                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.002                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.002         if best_ratio < cutoff:
2025-07-02 06:41:19.002             # no non-identical "pretty close" pair
2025-07-02 06:41:19.002             if eqi is None:
2025-07-02 06:41:19.002                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.002                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.002                 return
2025-07-02 06:41:19.002             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.002             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.002         else:
2025-07-02 06:41:19.002             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.002             eqi = None
2025-07-02 06:41:19.002
2025-07-02 06:41:19.003         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.003         # identical
2025-07-02 06:41:19.003
2025-07-02 06:41:19.003         # pump out diffs from before the synch point
2025-07-02 06:41:19.003         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.003
2025-07-02 06:41:19.003         # do intraline marking on the synch pair
2025-07-02 06:41:19.003         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.003         if eqi is None:
2025-07-02 06:41:19.003             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.003             atags = btags = ""
2025-07-02 06:41:19.003             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.003             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.003                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.003                 if tag == 'replace':
2025-07-02 06:41:19.003                     atags += '^' * la
2025-07-02 06:41:19.003                     btags += '^' * lb
2025-07-02 06:41:19.003                 elif tag == 'delete':
2025-07-02 06:41:19.003                     atags += '-' * la
2025-07-02 06:41:19.003                 elif tag == 'insert':
2025-07-02 06:41:19.003                     btags += '+' * lb
2025-07-02 06:41:19.004                 elif tag == 'equal':
2025-07-02 06:41:19.004                     atags += ' ' * la
2025-07-02 06:41:19.004                     btags += ' ' * lb
2025-07-02 06:41:19.004                 else:
2025-07-02 06:41:19.004                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.004             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.004         else:
2025-07-02 06:41:19.004             # the synch pair is identical
2025-07-02 06:41:19.004             yield '  ' + aelt
2025-07-02 06:41:19.004
2025-07-02 06:41:19.004         # pump out diffs from after the synch point
2025-07-02 06:41:19.004 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.004
2025-07-02 06:41:19.004 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.004 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.004
2025-07-02 06:41:19.004 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.004 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.005 alo = 496, ahi = 1101
2025-07-02 06:41:19.005 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.005 blo = 496, bhi = 1101
2025-07-02 06:41:19.005
2025-07-02 06:41:19.005     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.005         g = []
2025-07-02 06:41:19.005         if alo < ahi:
2025-07-02 06:41:19.005             if blo < bhi:
2025-07-02 06:41:19.005                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.005             else:
2025-07-02 06:41:19.005                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.005         elif blo < bhi:
2025-07-02 06:41:19.005             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.005
2025-07-02 06:41:19.005 >       yield from g
2025-07-02 06:41:19.005
2025-07-02 06:41:19.005 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.005 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.005
2025-07-02 06:41:19.006 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.006 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.006 alo = 496, ahi = 1101
2025-07-02 06:41:19.006 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.006 blo = 496, bhi = 1101
2025-07-02 06:41:19.006
2025-07-02 06:41:19.006     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.006         r"""
2025-07-02 06:41:19.006         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.006         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.006         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.006         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.006
2025-07-02 06:41:19.006         Example:
2025-07-02 06:41:19.006
2025-07-02 06:41:19.006         >>> d = Differ()
2025-07-02 06:41:19.006         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.006         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.006         >>> print(''.join(results), end="")
2025-07-02 06:41:19.007         - abcDefghiJkl
2025-07-02 06:41:19.007         + abcdefGhijkl
2025-07-02 06:41:19.007         """
2025-07-02 06:41:19.007
2025-07-02 06:41:19.007         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.007         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.007         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.007         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.007         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.007
2025-07-02 06:41:19.007         # search for the pair that matches best without being identical
2025-07-02 06:41:19.007         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.007         # on junk -- unless we have to)
2025-07-02 06:41:19.007         for j in range(blo, bhi):
2025-07-02 06:41:19.007             bj = b[j]
2025-07-02 06:41:19.007             cruncher.set_seq2(bj)
2025-07-02 06:41:19.007             for i in range(alo, ahi):
2025-07-02 06:41:19.007                 ai = a[i]
2025-07-02 06:41:19.008                 if ai == bj:
2025-07-02 06:41:19.008                     if eqi is None:
2025-07-02 06:41:19.008                         eqi, eqj = i, j
2025-07-02 06:41:19.008                     continue
2025-07-02 06:41:19.008                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.008                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.008                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.008                 # compares by a factor of 3.
2025-07-02 06:41:19.008                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.008                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.008                 # of the computation is cached by cruncher
2025-07-02 06:41:19.008                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.008                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.008                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.008                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.008         if best_ratio < cutoff:
2025-07-02 06:41:19.008             # no non-identical "pretty close" pair
2025-07-02 06:41:19.008             if eqi is None:
2025-07-02 06:41:19.008                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.009                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.009                 return
2025-07-02 06:41:19.009             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.009             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.009         else:
2025-07-02 06:41:19.009             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.009             eqi = None
2025-07-02 06:41:19.009
2025-07-02 06:41:19.009         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.009         # identical
2025-07-02 06:41:19.009
2025-07-02 06:41:19.009         # pump out diffs from before the synch point
2025-07-02 06:41:19.009         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.009
2025-07-02 06:41:19.009         # do intraline marking on the synch pair
2025-07-02 06:41:19.009         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.009         if eqi is None:
2025-07-02 06:41:19.009             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.010             atags = btags = ""
2025-07-02 06:41:19.010             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.010             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.010                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.010                 if tag == 'replace':
2025-07-02 06:41:19.010                     atags += '^' * la
2025-07-02 06:41:19.010                     btags += '^' * lb
2025-07-02 06:41:19.010                 elif tag == 'delete':
2025-07-02 06:41:19.010                     atags += '-' * la
2025-07-02 06:41:19.010                 elif tag == 'insert':
2025-07-02 06:41:19.010                     btags += '+' * lb
2025-07-02 06:41:19.010                 elif tag == 'equal':
2025-07-02 06:41:19.010                     atags += ' ' * la
2025-07-02 06:41:19.010                     btags += ' ' * lb
2025-07-02 06:41:19.010                 else:
2025-07-02 06:41:19.010                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.010             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.010         else:
2025-07-02 06:41:19.010             # the synch pair is identical
2025-07-02 06:41:19.011             yield '  ' + aelt
2025-07-02 06:41:19.011
2025-07-02 06:41:19.011         # pump out diffs from after the synch point
2025-07-02 06:41:19.011 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.011
2025-07-02 06:41:19.011 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.011 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.011
2025-07-02 06:41:19.011 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.011 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.011 alo = 497, ahi = 1101
2025-07-02 06:41:19.011 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.011 blo = 497, bhi = 1101
2025-07-02 06:41:19.011
2025-07-02 06:41:19.011     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.011         g = []
2025-07-02 06:41:19.011         if alo < ahi:
2025-07-02 06:41:19.011             if blo < bhi:
2025-07-02 06:41:19.011                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.011             else:
2025-07-02 06:41:19.012                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.012         elif blo < bhi:
2025-07-02 06:41:19.012             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.012
2025-07-02 06:41:19.012 >       yield from g
2025-07-02 06:41:19.012
2025-07-02 06:41:19.012 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.012 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.012
2025-07-02 06:41:19.012 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.012 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.012 alo = 497, ahi = 1101
2025-07-02 06:41:19.012 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.012 blo = 497, bhi = 1101
2025-07-02 06:41:19.012
2025-07-02 06:41:19.012     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.012         r"""
2025-07-02 06:41:19.012         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.012         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.012         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.013         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.013
2025-07-02 06:41:19.013         Example:
2025-07-02 06:41:19.013
2025-07-02 06:41:19.013         >>> d = Differ()
2025-07-02 06:41:19.013         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.013         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.013         >>> print(''.join(results), end="")
2025-07-02 06:41:19.013         - abcDefghiJkl
2025-07-02 06:41:19.013         + abcdefGhijkl
2025-07-02 06:41:19.013         """
2025-07-02 06:41:19.013
2025-07-02 06:41:19.013         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.013         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.013         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.013         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.013         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.013
2025-07-02 06:41:19.013         # search for the pair that matches best without being identical
2025-07-02 06:41:19.014         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.014         # on junk -- unless we have to)
2025-07-02 06:41:19.014         for j in range(blo, bhi):
2025-07-02 06:41:19.014             bj = b[j]
2025-07-02 06:41:19.014             cruncher.set_seq2(bj)
2025-07-02 06:41:19.014             for i in range(alo, ahi):
2025-07-02 06:41:19.014                 ai = a[i]
2025-07-02 06:41:19.014                 if ai == bj:
2025-07-02 06:41:19.014                     if eqi is None:
2025-07-02 06:41:19.014                         eqi, eqj = i, j
2025-07-02 06:41:19.014                     continue
2025-07-02 06:41:19.014                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.014                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.014                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.014                 # compares by a factor of 3.
2025-07-02 06:41:19.014                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.014                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.014                 # of the computation is cached by cruncher
2025-07-02 06:41:19.014                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.014                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.015                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.015                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.015         if best_ratio < cutoff:
2025-07-02 06:41:19.015             # no non-identical "pretty close" pair
2025-07-02 06:41:19.015             if eqi is None:
2025-07-02 06:41:19.015                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.015                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.015                 return
2025-07-02 06:41:19.015             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.015             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.015         else:
2025-07-02 06:41:19.015             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.015             eqi = None
2025-07-02 06:41:19.015
2025-07-02 06:41:19.015         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.015         # identical
2025-07-02 06:41:19.015
2025-07-02 06:41:19.015         # pump out diffs from before the synch point
2025-07-02 06:41:19.015         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.015
2025-07-02 06:41:19.016         # do intraline marking on the synch pair
2025-07-02 06:41:19.016         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.016         if eqi is None:
2025-07-02 06:41:19.016             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.016             atags = btags = ""
2025-07-02 06:41:19.016             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.016             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.016                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.016                 if tag == 'replace':
2025-07-02 06:41:19.016                     atags += '^' * la
2025-07-02 06:41:19.016                     btags += '^' * lb
2025-07-02 06:41:19.016                 elif tag == 'delete':
2025-07-02 06:41:19.016                     atags += '-' * la
2025-07-02 06:41:19.016                 elif tag == 'insert':
2025-07-02 06:41:19.016                     btags += '+' * lb
2025-07-02 06:41:19.016                 elif tag == 'equal':
2025-07-02 06:41:19.016                     atags += ' ' * la
2025-07-02 06:41:19.016                     btags += ' ' * lb
2025-07-02 06:41:19.016                 else:
2025-07-02 06:41:19.016                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.016             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.017         else:
2025-07-02 06:41:19.017             # the synch pair is identical
2025-07-02 06:41:19.017             yield '  ' + aelt
2025-07-02 06:41:19.017
2025-07-02 06:41:19.017         # pump out diffs from after the synch point
2025-07-02 06:41:19.017 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.017
2025-07-02 06:41:19.017 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.017 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.017
2025-07-02 06:41:19.017 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.017 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.017 alo = 498, ahi = 1101
2025-07-02 06:41:19.017 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.017 blo = 498, bhi = 1101
2025-07-02 06:41:19.017
2025-07-02 06:41:19.017     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.017         g = []
2025-07-02 06:41:19.018         if alo < ahi:
2025-07-02 06:41:19.018             if blo < bhi:
2025-07-02 06:41:19.018                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.018             else:
2025-07-02 06:41:19.018                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.018         elif blo < bhi:
2025-07-02 06:41:19.018             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.018
2025-07-02 06:41:19.018 >       yield from g
2025-07-02 06:41:19.018
2025-07-02 06:41:19.018 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.018 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.018
2025-07-02 06:41:19.018 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.018 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.018 alo = 498, ahi = 1101
2025-07-02 06:41:19.018 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.018 blo = 498, bhi = 1101
2025-07-02 06:41:19.018
2025-07-02 06:41:19.019     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.019         r"""
2025-07-02 06:41:19.019         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.019         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.019         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.019         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.019
2025-07-02 06:41:19.019         Example:
2025-07-02 06:41:19.019
2025-07-02 06:41:19.019         >>> d = Differ()
2025-07-02 06:41:19.019         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.019         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.019         >>> print(''.join(results), end="")
2025-07-02 06:41:19.019         - abcDefghiJkl
2025-07-02 06:41:19.019         + abcdefGhijkl
2025-07-02 06:41:19.019         """
2025-07-02 06:41:19.019
2025-07-02 06:41:19.019         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.020         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.020         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.020         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.020         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.020
2025-07-02 06:41:19.020         # search for the pair that matches best without being identical
2025-07-02 06:41:19.020         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.020         # on junk -- unless we have to)
2025-07-02 06:41:19.020         for j in range(blo, bhi):
2025-07-02 06:41:19.020             bj = b[j]
2025-07-02 06:41:19.020             cruncher.set_seq2(bj)
2025-07-02 06:41:19.020             for i in range(alo, ahi):
2025-07-02 06:41:19.020                 ai = a[i]
2025-07-02 06:41:19.020                 if ai == bj:
2025-07-02 06:41:19.020                     if eqi is None:
2025-07-02 06:41:19.020                         eqi, eqj = i, j
2025-07-02 06:41:19.020                     continue
2025-07-02 06:41:19.020                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.020                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.020                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.021                 # compares by a factor of 3.
2025-07-02 06:41:19.021                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.021                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.021                 # of the computation is cached by cruncher
2025-07-02 06:41:19.021                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.021                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.021                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.021                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.021         if best_ratio < cutoff:
2025-07-02 06:41:19.021             # no non-identical "pretty close" pair
2025-07-02 06:41:19.021             if eqi is None:
2025-07-02 06:41:19.021                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.021                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.021                 return
2025-07-02 06:41:19.021             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.021             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.021         else:
2025-07-02 06:41:19.021             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.022             eqi = None
2025-07-02 06:41:19.022
2025-07-02 06:41:19.022         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.022         # identical
2025-07-02 06:41:19.022
2025-07-02 06:41:19.022         # pump out diffs from before the synch point
2025-07-02 06:41:19.022         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.022
2025-07-02 06:41:19.022         # do intraline marking on the synch pair
2025-07-02 06:41:19.022         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.022         if eqi is None:
2025-07-02 06:41:19.022             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.022             atags = btags = ""
2025-07-02 06:41:19.022             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.022             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.022                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.022                 if tag == 'replace':
2025-07-02 06:41:19.022                     atags += '^' * la
2025-07-02 06:41:19.022                     btags += '^' * lb
2025-07-02 06:41:19.023                 elif tag == 'delete':
2025-07-02 06:41:19.023                     atags += '-' * la
2025-07-02 06:41:19.023                 elif tag == 'insert':
2025-07-02 06:41:19.023                     btags += '+' * lb
2025-07-02 06:41:19.023                 elif tag == 'equal':
2025-07-02 06:41:19.023                     atags += ' ' * la
2025-07-02 06:41:19.023                     btags += ' ' * lb
2025-07-02 06:41:19.023                 else:
2025-07-02 06:41:19.023                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.023             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.023         else:
2025-07-02 06:41:19.023             # the synch pair is identical
2025-07-02 06:41:19.023             yield '  ' + aelt
2025-07-02 06:41:19.023
2025-07-02 06:41:19.023         # pump out diffs from after the synch point
2025-07-02 06:41:19.023 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.023
2025-07-02 06:41:19.023 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.023 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.024
2025-07-02 06:41:19.024 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.024 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.024 alo = 499, ahi = 1101
2025-07-02 06:41:19.024 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.024 blo = 499, bhi = 1101
2025-07-02 06:41:19.024
2025-07-02 06:41:19.024     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.024         g = []
2025-07-02 06:41:19.024         if alo < ahi:
2025-07-02 06:41:19.024             if blo < bhi:
2025-07-02 06:41:19.024                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.024             else:
2025-07-02 06:41:19.024                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.024         elif blo < bhi:
2025-07-02 06:41:19.024             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.024
2025-07-02 06:41:19.024 >       yield from g
2025-07-02 06:41:19.024
2025-07-02 06:41:19.024 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.025 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.025
2025-07-02 06:41:19.025 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.025 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.025 alo = 499, ahi = 1101
2025-07-02 06:41:19.025 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.025 blo = 499, bhi = 1101
2025-07-02 06:41:19.025
2025-07-02 06:41:19.025     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.025         r"""
2025-07-02 06:41:19.025         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.025         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.025         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.025         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.025
2025-07-02 06:41:19.025         Example:
2025-07-02 06:41:19.025
2025-07-02 06:41:19.025         >>> d = Differ()
2025-07-02 06:41:19.025         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.025         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.026         >>> print(''.join(results), end="")
2025-07-02 06:41:19.026         - abcDefghiJkl
2025-07-02 06:41:19.026         + abcdefGhijkl
2025-07-02 06:41:19.026         """
2025-07-02 06:41:19.026
2025-07-02 06:41:19.026         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.026         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.026         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.026         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.026         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.026
2025-07-02 06:41:19.026         # search for the pair that matches best without being identical
2025-07-02 06:41:19.026         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.026         # on junk -- unless we have to)
2025-07-02 06:41:19.026         for j in range(blo, bhi):
2025-07-02 06:41:19.026             bj = b[j]
2025-07-02 06:41:19.026             cruncher.set_seq2(bj)
2025-07-02 06:41:19.027             for i in range(alo, ahi):
2025-07-02 06:41:19.027                 ai = a[i]
2025-07-02 06:41:19.027                 if ai == bj:
2025-07-02 06:41:19.027                     if eqi is None:
2025-07-02 06:41:19.027                         eqi, eqj = i, j
2025-07-02 06:41:19.027                     continue
2025-07-02 06:41:19.027                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.027                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.027                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.027                 # compares by a factor of 3.
2025-07-02 06:41:19.027                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.027                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.027                 # of the computation is cached by cruncher
2025-07-02 06:41:19.027                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.027                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.027                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.027                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.027         if best_ratio < cutoff:
2025-07-02 06:41:19.027             # no non-identical "pretty close" pair
2025-07-02 06:41:19.028             if eqi is None:
2025-07-02 06:41:19.028                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.028                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.028                 return
2025-07-02 06:41:19.028             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.028             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.028         else:
2025-07-02 06:41:19.028             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.028             eqi = None
2025-07-02 06:41:19.028
2025-07-02 06:41:19.028         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.028         # identical
2025-07-02 06:41:19.028
2025-07-02 06:41:19.028         # pump out diffs from before the synch point
2025-07-02 06:41:19.028         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.028
2025-07-02 06:41:19.028         # do intraline marking on the synch pair
2025-07-02 06:41:19.028         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.028         if eqi is None:
2025-07-02 06:41:19.029             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.029             atags = btags = ""
2025-07-02 06:41:19.029             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.029             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.029                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.029                 if tag == 'replace':
2025-07-02 06:41:19.029                     atags += '^' * la
2025-07-02 06:41:19.029                     btags += '^' * lb
2025-07-02 06:41:19.029                 elif tag == 'delete':
2025-07-02 06:41:19.029                     atags += '-' * la
2025-07-02 06:41:19.029                 elif tag == 'insert':
2025-07-02 06:41:19.029                     btags += '+' * lb
2025-07-02 06:41:19.029                 elif tag == 'equal':
2025-07-02 06:41:19.029                     atags += ' ' * la
2025-07-02 06:41:19.029                     btags += ' ' * lb
2025-07-02 06:41:19.029                 else:
2025-07-02 06:41:19.029                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.029             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.029         else:
2025-07-02 06:41:19.029             # the synch pair is identical
2025-07-02 06:41:19.029             yield '  ' + aelt
2025-07-02 06:41:19.030
2025-07-02 06:41:19.030         # pump out diffs from after the synch point
2025-07-02 06:41:19.030 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.030
2025-07-02 06:41:19.030 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.030 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.030
2025-07-02 06:41:19.030 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.030 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.030 alo = 500, ahi = 1101
2025-07-02 06:41:19.030 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.030 blo = 500, bhi = 1101
2025-07-02 06:41:19.030
2025-07-02 06:41:19.030     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.030         g = []
2025-07-02 06:41:19.030         if alo < ahi:
2025-07-02 06:41:19.030             if blo < bhi:
2025-07-02 06:41:19.030                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.030             else:
2025-07-02 06:41:19.030                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.031         elif blo < bhi:
2025-07-02 06:41:19.031             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.031
2025-07-02 06:41:19.031 >       yield from g
2025-07-02 06:41:19.031
2025-07-02 06:41:19.031 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.031 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.031
2025-07-02 06:41:19.031 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.031 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.031 alo = 500, ahi = 1101
2025-07-02 06:41:19.031 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.031 blo = 500, bhi = 1101
2025-07-02 06:41:19.031
2025-07-02 06:41:19.031     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.031         r"""
2025-07-02 06:41:19.031         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.031         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.031         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.031         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.032
2025-07-02 06:41:19.032         Example:
2025-07-02 06:41:19.032
2025-07-02 06:41:19.032         >>> d = Differ()
2025-07-02 06:41:19.032         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.032         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.032         >>> print(''.join(results), end="")
2025-07-02 06:41:19.032         - abcDefghiJkl
2025-07-02 06:41:19.032         + abcdefGhijkl
2025-07-02 06:41:19.032         """
2025-07-02 06:41:19.032
2025-07-02 06:41:19.032         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.032         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.032         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.032         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.032         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.032
2025-07-02 06:41:19.032         # search for the pair that matches best without being identical
2025-07-02 06:41:19.033         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.033         # on junk -- unless we have to)
2025-07-02 06:41:19.033         for j in range(blo, bhi):
2025-07-02 06:41:19.033             bj = b[j]
2025-07-02 06:41:19.033             cruncher.set_seq2(bj)
2025-07-02 06:41:19.033             for i in range(alo, ahi):
2025-07-02 06:41:19.033                 ai = a[i]
2025-07-02 06:41:19.033                 if ai == bj:
2025-07-02 06:41:19.033                     if eqi is None:
2025-07-02 06:41:19.033                         eqi, eqj = i, j
2025-07-02 06:41:19.033                     continue
2025-07-02 06:41:19.033                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.033                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.033                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.033                 # compares by a factor of 3.
2025-07-02 06:41:19.033                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.033                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.033                 # of the computation is cached by cruncher
2025-07-02 06:41:19.033                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.033                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.033                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.034                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.034         if best_ratio < cutoff:
2025-07-02 06:41:19.034             # no non-identical "pretty close" pair
2025-07-02 06:41:19.034             if eqi is None:
2025-07-02 06:41:19.034                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.034                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.034                 return
2025-07-02 06:41:19.034             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.034             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.034         else:
2025-07-02 06:41:19.034             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.034             eqi = None
2025-07-02 06:41:19.034
2025-07-02 06:41:19.034         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.034         # identical
2025-07-02 06:41:19.034
2025-07-02 06:41:19.034         # pump out diffs from before the synch point
2025-07-02 06:41:19.034         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.034
2025-07-02 06:41:19.034         # do intraline marking on the synch pair
2025-07-02 06:41:19.035         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.035         if eqi is None:
2025-07-02 06:41:19.035             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.035             atags = btags = ""
2025-07-02 06:41:19.035             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.035             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.035                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.035                 if tag == 'replace':
2025-07-02 06:41:19.035                     atags += '^' * la
2025-07-02 06:41:19.035                     btags += '^' * lb
2025-07-02 06:41:19.035                 elif tag == 'delete':
2025-07-02 06:41:19.035                     atags += '-' * la
2025-07-02 06:41:19.035                 elif tag == 'insert':
2025-07-02 06:41:19.035                     btags += '+' * lb
2025-07-02 06:41:19.035                 elif tag == 'equal':
2025-07-02 06:41:19.035                     atags += ' ' * la
2025-07-02 06:41:19.035                     btags += ' ' * lb
2025-07-02 06:41:19.035                 else:
2025-07-02 06:41:19.036                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.036             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.036         else:
2025-07-02 06:41:19.036             # the synch pair is identical
2025-07-02 06:41:19.036             yield '  ' + aelt
2025-07-02 06:41:19.036
2025-07-02 06:41:19.036         # pump out diffs from after the synch point
2025-07-02 06:41:19.036 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.036
2025-07-02 06:41:19.036 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.036 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.036
2025-07-02 06:41:19.036 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.036 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.036 alo = 501, ahi = 1101
2025-07-02 06:41:19.036 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.036 blo = 501, bhi = 1101
2025-07-02 06:41:19.036
2025-07-02 06:41:19.036     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.037         g = []
2025-07-02 06:41:19.037         if alo < ahi:
2025-07-02 06:41:19.037             if blo < bhi:
2025-07-02 06:41:19.037                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.037             else:
2025-07-02 06:41:19.037                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.037         elif blo < bhi:
2025-07-02 06:41:19.037             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.037
2025-07-02 06:41:19.037 >       yield from g
2025-07-02 06:41:19.037
2025-07-02 06:41:19.037 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.037 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.037
2025-07-02 06:41:19.037 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.037 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.037 alo = 501, ahi = 1101
2025-07-02 06:41:19.037 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.038 blo = 501, bhi = 1101
2025-07-02 06:41:19.038
2025-07-02 06:41:19.038     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.038         r"""
2025-07-02 06:41:19.038         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.038         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.038         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.038         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.038
2025-07-02 06:41:19.038         Example:
2025-07-02 06:41:19.038
2025-07-02 06:41:19.038         >>> d = Differ()
2025-07-02 06:41:19.038         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.038         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.038         >>> print(''.join(results), end="")
2025-07-02 06:41:19.038         - abcDefghiJkl
2025-07-02 06:41:19.038         + abcdefGhijkl
2025-07-02 06:41:19.039         """
2025-07-02 06:41:19.039
2025-07-02 06:41:19.039         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.039         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.039         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.039         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.039         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.039
2025-07-02 06:41:19.039         # search for the pair that matches best without being identical
2025-07-02 06:41:19.039         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.039         # on junk -- unless we have to)
2025-07-02 06:41:19.039         for j in range(blo, bhi):
2025-07-02 06:41:19.039             bj = b[j]
2025-07-02 06:41:19.039             cruncher.set_seq2(bj)
2025-07-02 06:41:19.039             for i in range(alo, ahi):
2025-07-02 06:41:19.039                 ai = a[i]
2025-07-02 06:41:19.039                 if ai == bj:
2025-07-02 06:41:19.039                     if eqi is None:
2025-07-02 06:41:19.039                         eqi, eqj = i, j
2025-07-02 06:41:19.039                     continue
2025-07-02 06:41:19.039                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.040                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.040                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.040                 # compares by a factor of 3.
2025-07-02 06:41:19.040                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.040                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.040                 # of the computation is cached by cruncher
2025-07-02 06:41:19.040                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.040                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.040                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.040                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.040         if best_ratio < cutoff:
2025-07-02 06:41:19.040             # no non-identical "pretty close" pair
2025-07-02 06:41:19.040             if eqi is None:
2025-07-02 06:41:19.040                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.040                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.040                 return
2025-07-02 06:41:19.040             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.040             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.040         else:
2025-07-02 06:41:19.040             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.041             eqi = None
2025-07-02 06:41:19.041
2025-07-02 06:41:19.041         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.041         # identical
2025-07-02 06:41:19.041
2025-07-02 06:41:19.041         # pump out diffs from before the synch point
2025-07-02 06:41:19.041         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.041
2025-07-02 06:41:19.041         # do intraline marking on the synch pair
2025-07-02 06:41:19.041         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.041         if eqi is None:
2025-07-02 06:41:19.041             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.041             atags = btags = ""
2025-07-02 06:41:19.041             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.041             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.041                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.041                 if tag == 'replace':
2025-07-02 06:41:19.041                     atags += '^' * la
2025-07-02 06:41:19.041                     btags += '^' * lb
2025-07-02 06:41:19.042                 elif tag == 'delete':
2025-07-02 06:41:19.042                     atags += '-' * la
2025-07-02 06:41:19.042                 elif tag == 'insert':
2025-07-02 06:41:19.042                     btags += '+' * lb
2025-07-02 06:41:19.042                 elif tag == 'equal':
2025-07-02 06:41:19.042                     atags += ' ' * la
2025-07-02 06:41:19.042                     btags += ' ' * lb
2025-07-02 06:41:19.042                 else:
2025-07-02 06:41:19.042                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.042             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.042         else:
2025-07-02 06:41:19.042             # the synch pair is identical
2025-07-02 06:41:19.042             yield '  ' + aelt
2025-07-02 06:41:19.042
2025-07-02 06:41:19.042         # pump out diffs from after the synch point
2025-07-02 06:41:19.042 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.042
2025-07-02 06:41:19.042 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.042 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.042
2025-07-02 06:41:19.042 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.043 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.044 alo = 502, ahi = 1101
2025-07-02 06:41:19.044 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.044 blo = 502, bhi = 1101
2025-07-02 06:41:19.044
2025-07-02 06:41:19.044     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.044         g = []
2025-07-02 06:41:19.044         if alo < ahi:
2025-07-02 06:41:19.044             if blo < bhi:
2025-07-02 06:41:19.044                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.044             else:
2025-07-02 06:41:19.044                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.044         elif blo < bhi:
2025-07-02 06:41:19.044             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.044
2025-07-02 06:41:19.044 >       yield from g
2025-07-02 06:41:19.044
2025-07-02 06:41:19.044 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.044 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.044
2025-07-02 06:41:19.045 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.045 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.045 alo = 502, ahi = 1101
2025-07-02 06:41:19.045 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.045 blo = 502, bhi = 1101
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.045         r"""
2025-07-02 06:41:19.045         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.045         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.045         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.045         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045         Example:
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045         >>> d = Differ()
2025-07-02 06:41:19.045         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.045         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.045         >>> print(''.join(results), end="")
2025-07-02 06:41:19.045         - abcDefghiJkl
2025-07-02 06:41:19.045         + abcdefGhijkl
2025-07-02 06:41:19.045         """
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.045         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.045         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.045         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.045         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.045
2025-07-02 06:41:19.045         # search for the pair that matches best without being identical
2025-07-02 06:41:19.045         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.045         # on junk -- unless we have to)
2025-07-02 06:41:19.045         for j in range(blo, bhi):
2025-07-02 06:41:19.045             bj = b[j]
2025-07-02 06:41:19.046             cruncher.set_seq2(bj)
2025-07-02 06:41:19.046             for i in range(alo, ahi):
2025-07-02 06:41:19.046                 ai = a[i]
2025-07-02 06:41:19.046                 if ai == bj:
2025-07-02 06:41:19.046                     if eqi is None:
2025-07-02 06:41:19.046                         eqi, eqj = i, j
2025-07-02 06:41:19.046                     continue
2025-07-02 06:41:19.046                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.046                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.046                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.046                 # compares by a factor of 3.
2025-07-02 06:41:19.046                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.046                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.046                 # of the computation is cached by cruncher
2025-07-02 06:41:19.046                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.046                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.046                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.046                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.046         if best_ratio < cutoff:
2025-07-02 06:41:19.046             # no non-identical "pretty close" pair
2025-07-02 06:41:19.047             if eqi is None:
2025-07-02 06:41:19.047                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.047                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.047                 return
2025-07-02 06:41:19.047             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.047             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.047         else:
2025-07-02 06:41:19.047             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.047             eqi = None
2025-07-02 06:41:19.047
2025-07-02 06:41:19.047         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.047         # identical
2025-07-02 06:41:19.047
2025-07-02 06:41:19.047         # pump out diffs from before the synch point
2025-07-02 06:41:19.047         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.047
2025-07-02 06:41:19.047         # do intraline marking on the synch pair
2025-07-02 06:41:19.047         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.047         if eqi is None:
2025-07-02 06:41:19.047             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.048             atags = btags = ""
2025-07-02 06:41:19.048             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.048             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.048                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.048                 if tag == 'replace':
2025-07-02 06:41:19.048                     atags += '^' * la
2025-07-02 06:41:19.048                     btags += '^' * lb
2025-07-02 06:41:19.048                 elif tag == 'delete':
2025-07-02 06:41:19.048                     atags += '-' * la
2025-07-02 06:41:19.048                 elif tag == 'insert':
2025-07-02 06:41:19.048                     btags += '+' * lb
2025-07-02 06:41:19.048                 elif tag == 'equal':
2025-07-02 06:41:19.048                     atags += ' ' * la
2025-07-02 06:41:19.048                     btags += ' ' * lb
2025-07-02 06:41:19.048                 else:
2025-07-02 06:41:19.048                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.048             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.048         else:
2025-07-02 06:41:19.048             # the synch pair is identical
2025-07-02 06:41:19.048             yield '  ' + aelt
2025-07-02 06:41:19.049
2025-07-02 06:41:19.049         # pump out diffs from after the synch point
2025-07-02 06:41:19.049 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.049
2025-07-02 06:41:19.049 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.049 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.049
2025-07-02 06:41:19.049 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.049 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.049 alo = 503, ahi = 1101
2025-07-02 06:41:19.049 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.049 blo = 503, bhi = 1101
2025-07-02 06:41:19.049
2025-07-02 06:41:19.049     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.049         g = []
2025-07-02 06:41:19.049         if alo < ahi:
2025-07-02 06:41:19.049             if blo < bhi:
2025-07-02 06:41:19.049                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.049             else:
2025-07-02 06:41:19.049                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.050         elif blo < bhi:
2025-07-02 06:41:19.050             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.050
2025-07-02 06:41:19.050 >       yield from g
2025-07-02 06:41:19.050
2025-07-02 06:41:19.050 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.050 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.050
2025-07-02 06:41:19.050 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.050 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.050 alo = 503, ahi = 1101
2025-07-02 06:41:19.050 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.050 blo = 503, bhi = 1101
2025-07-02 06:41:19.050
2025-07-02 06:41:19.050     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.050         r"""
2025-07-02 06:41:19.050         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.050         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.050         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.050         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.051
2025-07-02 06:41:19.051         Example:
2025-07-02 06:41:19.051
2025-07-02 06:41:19.051         >>> d = Differ()
2025-07-02 06:41:19.051         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.051         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.051         >>> print(''.join(results), end="")
2025-07-02 06:41:19.051         - abcDefghiJkl
2025-07-02 06:41:19.051         + abcdefGhijkl
2025-07-02 06:41:19.051         """
2025-07-02 06:41:19.051
2025-07-02 06:41:19.051         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.051         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.051         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.051         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.051         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.051
2025-07-02 06:41:19.051         # search for the pair that matches best without being identical
2025-07-02 06:41:19.051         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.052         # on junk -- unless we have to)
2025-07-02 06:41:19.052         for j in range(blo, bhi):
2025-07-02 06:41:19.052             bj = b[j]
2025-07-02 06:41:19.052             cruncher.set_seq2(bj)
2025-07-02 06:41:19.052             for i in range(alo, ahi):
2025-07-02 06:41:19.052                 ai = a[i]
2025-07-02 06:41:19.052                 if ai == bj:
2025-07-02 06:41:19.052                     if eqi is None:
2025-07-02 06:41:19.052                         eqi, eqj = i, j
2025-07-02 06:41:19.052                     continue
2025-07-02 06:41:19.052                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.052                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.052                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.052                 # compares by a factor of 3.
2025-07-02 06:41:19.052                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.052                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.052                 # of the computation is cached by cruncher
2025-07-02 06:41:19.052                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.053                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.053                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.053                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.053         if best_ratio < cutoff:
2025-07-02 06:41:19.053             # no non-identical "pretty close" pair
2025-07-02 06:41:19.053             if eqi is None:
2025-07-02 06:41:19.053                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.053                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.053                 return
2025-07-02 06:41:19.053             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.053             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.053         else:
2025-07-02 06:41:19.053             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.053             eqi = None
2025-07-02 06:41:19.053
2025-07-02 06:41:19.053         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.054         # identical
2025-07-02 06:41:19.054
2025-07-02 06:41:19.054         # pump out diffs from before the synch point
2025-07-02 06:41:19.054         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.054
2025-07-02 06:41:19.054         # do intraline marking on the synch pair
2025-07-02 06:41:19.054         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.054         if eqi is None:
2025-07-02 06:41:19.054             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.054             atags = btags = ""
2025-07-02 06:41:19.054             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.054             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.054                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.054                 if tag == 'replace':
2025-07-02 06:41:19.054                     atags += '^' * la
2025-07-02 06:41:19.054                     btags += '^' * lb
2025-07-02 06:41:19.054                 elif tag == 'delete':
2025-07-02 06:41:19.054                     atags += '-' * la
2025-07-02 06:41:19.054                 elif tag == 'insert':
2025-07-02 06:41:19.054                     btags += '+' * lb
2025-07-02 06:41:19.055                 elif tag == 'equal':
2025-07-02 06:41:19.055                     atags += ' ' * la
2025-07-02 06:41:19.055                     btags += ' ' * lb
2025-07-02 06:41:19.055                 else:
2025-07-02 06:41:19.055                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.055             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.055         else:
2025-07-02 06:41:19.055             # the synch pair is identical
2025-07-02 06:41:19.055             yield '  ' + aelt
2025-07-02 06:41:19.055
2025-07-02 06:41:19.055         # pump out diffs from after the synch point
2025-07-02 06:41:19.055 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.055
2025-07-02 06:41:19.055 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.055 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.055
2025-07-02 06:41:19.055 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.055 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.055 alo = 504, ahi = 1101
2025-07-02 06:41:19.056 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.056 blo = 504, bhi = 1101
2025-07-02 06:41:19.056
2025-07-02 06:41:19.056     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.056         g = []
2025-07-02 06:41:19.056         if alo < ahi:
2025-07-02 06:41:19.056             if blo < bhi:
2025-07-02 06:41:19.056                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.056             else:
2025-07-02 06:41:19.056                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.056         elif blo < bhi:
2025-07-02 06:41:19.056             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.056
2025-07-02 06:41:19.056 >       yield from g
2025-07-02 06:41:19.056
2025-07-02 06:41:19.056 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.056 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.056
2025-07-02 06:41:19.056 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.056 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.057 alo = 504, ahi = 1101
2025-07-02 06:41:19.057 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.057 blo = 504, bhi = 1101
2025-07-02 06:41:19.057
2025-07-02 06:41:19.057     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.057         r"""
2025-07-02 06:41:19.057         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.057         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.057         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.057         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.057
2025-07-02 06:41:19.057         Example:
2025-07-02 06:41:19.057
2025-07-02 06:41:19.057         >>> d = Differ()
2025-07-02 06:41:19.057         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.057         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.057         >>> print(''.join(results), end="")
2025-07-02 06:41:19.057         - abcDefghiJkl
2025-07-02 06:41:19.058         + abcdefGhijkl
2025-07-02 06:41:19.058         """
2025-07-02 06:41:19.058
2025-07-02 06:41:19.058         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.058         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.058         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.058         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.058         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.058
2025-07-02 06:41:19.058         # search for the pair that matches best without being identical
2025-07-02 06:41:19.058         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.058         # on junk -- unless we have to)
2025-07-02 06:41:19.058         for j in range(blo, bhi):
2025-07-02 06:41:19.058             bj = b[j]
2025-07-02 06:41:19.058             cruncher.set_seq2(bj)
2025-07-02 06:41:19.058             for i in range(alo, ahi):
2025-07-02 06:41:19.058                 ai = a[i]
2025-07-02 06:41:19.058                 if ai == bj:
2025-07-02 06:41:19.059                     if eqi is None:
2025-07-02 06:41:19.059                         eqi, eqj = i, j
2025-07-02 06:41:19.059                     continue
2025-07-02 06:41:19.059                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.059                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.059                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.059                 # compares by a factor of 3.
2025-07-02 06:41:19.059                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.059                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.059                 # of the computation is cached by cruncher
2025-07-02 06:41:19.059                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.059                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.059                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.059                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.059         if best_ratio < cutoff:
2025-07-02 06:41:19.059             # no non-identical "pretty close" pair
2025-07-02 06:41:19.059             if eqi is None:
2025-07-02 06:41:19.059                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.060                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.060                 return
2025-07-02 06:41:19.060             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.060             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.060         else:
2025-07-02 06:41:19.060             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.060             eqi = None
2025-07-02 06:41:19.060
2025-07-02 06:41:19.060         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.060         # identical
2025-07-02 06:41:19.060
2025-07-02 06:41:19.060         # pump out diffs from before the synch point
2025-07-02 06:41:19.060         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.060
2025-07-02 06:41:19.060         # do intraline marking on the synch pair
2025-07-02 06:41:19.060         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.060         if eqi is None:
2025-07-02 06:41:19.060             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.061             atags = btags = ""
2025-07-02 06:41:19.061             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.061             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.061                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.061                 if tag == 'replace':
2025-07-02 06:41:19.061                     atags += '^' * la
2025-07-02 06:41:19.061                     btags += '^' * lb
2025-07-02 06:41:19.061                 elif tag == 'delete':
2025-07-02 06:41:19.061                     atags += '-' * la
2025-07-02 06:41:19.061                 elif tag == 'insert':
2025-07-02 06:41:19.061                     btags += '+' * lb
2025-07-02 06:41:19.061                 elif tag == 'equal':
2025-07-02 06:41:19.061                     atags += ' ' * la
2025-07-02 06:41:19.061                     btags += ' ' * lb
2025-07-02 06:41:19.061                 else:
2025-07-02 06:41:19.061                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.061             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.061         else:
2025-07-02 06:41:19.061             # the synch pair is identical
2025-07-02 06:41:19.062             yield '  ' + aelt
2025-07-02 06:41:19.062
2025-07-02 06:41:19.062         # pump out diffs from after the synch point
2025-07-02 06:41:19.062 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.062
2025-07-02 06:41:19.062 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.062 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.062
2025-07-02 06:41:19.062 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.062 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.062 alo = 505, ahi = 1101
2025-07-02 06:41:19.062 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.062 blo = 505, bhi = 1101
2025-07-02 06:41:19.062
2025-07-02 06:41:19.062     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.062         g = []
2025-07-02 06:41:19.062         if alo < ahi:
2025-07-02 06:41:19.062             if blo < bhi:
2025-07-02 06:41:19.063                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.063             else:
2025-07-02 06:41:19.063                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.063         elif blo < bhi:
2025-07-02 06:41:19.063             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.063
2025-07-02 06:41:19.063 >       yield from g
2025-07-02 06:41:19.063
2025-07-02 06:41:19.063 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.063 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.063
2025-07-02 06:41:19.063 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.063 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.063 alo = 505, ahi = 1101
2025-07-02 06:41:19.063 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.063 blo = 505, bhi = 1101
2025-07-02 06:41:19.063
2025-07-02 06:41:19.063     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.063         r"""
2025-07-02 06:41:19.064         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.064         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.064         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.064         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.064
2025-07-02 06:41:19.064         Example:
2025-07-02 06:41:19.064
2025-07-02 06:41:19.064         >>> d = Differ()
2025-07-02 06:41:19.064         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.064         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.064         >>> print(''.join(results), end="")
2025-07-02 06:41:19.064         - abcDefghiJkl
2025-07-02 06:41:19.064         + abcdefGhijkl
2025-07-02 06:41:19.064         """
2025-07-02 06:41:19.064
2025-07-02 06:41:19.064         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.064         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.064         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.064         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.065         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.065
2025-07-02 06:41:19.065         # search for the pair that matches best without being identical
2025-07-02 06:41:19.065         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.065         # on junk -- unless we have to)
2025-07-02 06:41:19.065         for j in range(blo, bhi):
2025-07-02 06:41:19.065             bj = b[j]
2025-07-02 06:41:19.065             cruncher.set_seq2(bj)
2025-07-02 06:41:19.065             for i in range(alo, ahi):
2025-07-02 06:41:19.065                 ai = a[i]
2025-07-02 06:41:19.065                 if ai == bj:
2025-07-02 06:41:19.065                     if eqi is None:
2025-07-02 06:41:19.065                         eqi, eqj = i, j
2025-07-02 06:41:19.065                     continue
2025-07-02 06:41:19.065                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.065                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.065                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.065                 # compares by a factor of 3.
2025-07-02 06:41:19.065                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.065                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.066                 # of the computation is cached by cruncher
2025-07-02 06:41:19.066                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.066                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.066                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.066                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.066         if best_ratio < cutoff:
2025-07-02 06:41:19.066             # no non-identical "pretty close" pair
2025-07-02 06:41:19.066             if eqi is None:
2025-07-02 06:41:19.066                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.066                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.066                 return
2025-07-02 06:41:19.066             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.066             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.066         else:
2025-07-02 06:41:19.066             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.066             eqi = None
2025-07-02 06:41:19.066
2025-07-02 06:41:19.066         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.066         # identical
2025-07-02 06:41:19.066
2025-07-02 06:41:19.067         # pump out diffs from before the synch point
2025-07-02 06:41:19.067         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.067
2025-07-02 06:41:19.067         # do intraline marking on the synch pair
2025-07-02 06:41:19.067         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.067         if eqi is None:
2025-07-02 06:41:19.067             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.067             atags = btags = ""
2025-07-02 06:41:19.067             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.067             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.067                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.067                 if tag == 'replace':
2025-07-02 06:41:19.067                     atags += '^' * la
2025-07-02 06:41:19.067                     btags += '^' * lb
2025-07-02 06:41:19.067                 elif tag == 'delete':
2025-07-02 06:41:19.067                     atags += '-' * la
2025-07-02 06:41:19.067                 elif tag == 'insert':
2025-07-02 06:41:19.067                     btags += '+' * lb
2025-07-02 06:41:19.067                 elif tag == 'equal':
2025-07-02 06:41:19.067                     atags += ' ' * la
2025-07-02 06:41:19.067                     btags += ' ' * lb
2025-07-02 06:41:19.068                 else:
2025-07-02 06:41:19.068                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.068             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.068         else:
2025-07-02 06:41:19.068             # the synch pair is identical
2025-07-02 06:41:19.068             yield '  ' + aelt
2025-07-02 06:41:19.068
2025-07-02 06:41:19.068         # pump out diffs from after the synch point
2025-07-02 06:41:19.068 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.068
2025-07-02 06:41:19.068 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.068 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.068
2025-07-02 06:41:19.068 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.068 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.068 alo = 506, ahi = 1101
2025-07-02 06:41:19.068 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.068 blo = 506, bhi = 1101
2025-07-02 06:41:19.068
2025-07-02 06:41:19.068     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.069         g = []
2025-07-02 06:41:19.069         if alo < ahi:
2025-07-02 06:41:19.069             if blo < bhi:
2025-07-02 06:41:19.069                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.069             else:
2025-07-02 06:41:19.069                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.069         elif blo < bhi:
2025-07-02 06:41:19.069             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.069
2025-07-02 06:41:19.069 >       yield from g
2025-07-02 06:41:19.069
2025-07-02 06:41:19.069 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.069 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.069
2025-07-02 06:41:19.069 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.069 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.069 alo = 506, ahi = 1101
2025-07-02 06:41:19.070 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.070 blo = 506, bhi = 1101
2025-07-02 06:41:19.070
2025-07-02 06:41:19.070     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.070         r"""
2025-07-02 06:41:19.070         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.070         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.070         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.070         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.070
2025-07-02 06:41:19.070         Example:
2025-07-02 06:41:19.070
2025-07-02 06:41:19.070         >>> d = Differ()
2025-07-02 06:41:19.070         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.070         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.070         >>> print(''.join(results), end="")
2025-07-02 06:41:19.070         - abcDefghiJkl
2025-07-02 06:41:19.071         + abcdefGhijkl
2025-07-02 06:41:19.071         """
2025-07-02 06:41:19.071
2025-07-02 06:41:19.071         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.071         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.071         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.071         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.071         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.071
2025-07-02 06:41:19.071         # search for the pair that matches best without being identical
2025-07-02 06:41:19.071         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.071         # on junk -- unless we have to)
2025-07-02 06:41:19.071         for j in range(blo, bhi):
2025-07-02 06:41:19.071             bj = b[j]
2025-07-02 06:41:19.071             cruncher.set_seq2(bj)
2025-07-02 06:41:19.071             for i in range(alo, ahi):
2025-07-02 06:41:19.071                 ai = a[i]
2025-07-02 06:41:19.071                 if ai == bj:
2025-07-02 06:41:19.072                     if eqi is None:
2025-07-02 06:41:19.072                         eqi, eqj = i, j
2025-07-02 06:41:19.072                     continue
2025-07-02 06:41:19.072                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.072                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.072                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.072                 # compares by a factor of 3.
2025-07-02 06:41:19.072                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.072                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.072                 # of the computation is cached by cruncher
2025-07-02 06:41:19.072                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.072                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.072                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.072                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.072         if best_ratio < cutoff:
2025-07-02 06:41:19.072             # no non-identical "pretty close" pair
2025-07-02 06:41:19.072             if eqi is None:
2025-07-02 06:41:19.072                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.072                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.073                 return
2025-07-02 06:41:19.073             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.073             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.073         else:
2025-07-02 06:41:19.073             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.073             eqi = None
2025-07-02 06:41:19.073
2025-07-02 06:41:19.073         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.073         # identical
2025-07-02 06:41:19.073
2025-07-02 06:41:19.073         # pump out diffs from before the synch point
2025-07-02 06:41:19.073         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.073
2025-07-02 06:41:19.073         # do intraline marking on the synch pair
2025-07-02 06:41:19.073         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.073         if eqi is None:
2025-07-02 06:41:19.073             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.073             atags = btags = ""
2025-07-02 06:41:19.073             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.073             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.074                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.074                 if tag == 'replace':
2025-07-02 06:41:19.074                     atags += '^' * la
2025-07-02 06:41:19.074                     btags += '^' * lb
2025-07-02 06:41:19.074                 elif tag == 'delete':
2025-07-02 06:41:19.074                     atags += '-' * la
2025-07-02 06:41:19.074                 elif tag == 'insert':
2025-07-02 06:41:19.074                     btags += '+' * lb
2025-07-02 06:41:19.074                 elif tag == 'equal':
2025-07-02 06:41:19.074                     atags += ' ' * la
2025-07-02 06:41:19.074                     btags += ' ' * lb
2025-07-02 06:41:19.074                 else:
2025-07-02 06:41:19.074                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.074             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.074         else:
2025-07-02 06:41:19.074             # the synch pair is identical
2025-07-02 06:41:19.074             yield '  ' + aelt
2025-07-02 06:41:19.074
2025-07-02 06:41:19.074         # pump out diffs from after the synch point
2025-07-02 06:41:19.074 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.074
2025-07-02 06:41:19.075 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.075 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.075
2025-07-02 06:41:19.075 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.075 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.075 alo = 507, ahi = 1101
2025-07-02 06:41:19.075 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.075 blo = 507, bhi = 1101
2025-07-02 06:41:19.075
2025-07-02 06:41:19.075     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.075         g = []
2025-07-02 06:41:19.075         if alo < ahi:
2025-07-02 06:41:19.075             if blo < bhi:
2025-07-02 06:41:19.075                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.075             else:
2025-07-02 06:41:19.075                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.075         elif blo < bhi:
2025-07-02 06:41:19.075             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.075
2025-07-02 06:41:19.075 >       yield from g
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.076 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.076 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.076 alo = 507, ahi = 1101
2025-07-02 06:41:19.076 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.076 blo = 507, bhi = 1101
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.076         r"""
2025-07-02 06:41:19.076         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.076         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.076         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.076         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076         Example:
2025-07-02 06:41:19.076
2025-07-02 06:41:19.076         >>> d = Differ()
2025-07-02 06:41:19.077         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.077         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.077         >>> print(''.join(results), end="")
2025-07-02 06:41:19.077         - abcDefghiJkl
2025-07-02 06:41:19.077         + abcdefGhijkl
2025-07-02 06:41:19.077         """
2025-07-02 06:41:19.077
2025-07-02 06:41:19.077         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.077         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.077         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.077         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.077         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.077
2025-07-02 06:41:19.077         # search for the pair that matches best without being identical
2025-07-02 06:41:19.077         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.077         # on junk -- unless we have to)
2025-07-02 06:41:19.077         for j in range(blo, bhi):
2025-07-02 06:41:19.077             bj = b[j]
2025-07-02 06:41:19.077             cruncher.set_seq2(bj)
2025-07-02 06:41:19.078             for i in range(alo, ahi):
2025-07-02 06:41:19.078                 ai = a[i]
2025-07-02 06:41:19.078                 if ai == bj:
2025-07-02 06:41:19.078                     if eqi is None:
2025-07-02 06:41:19.078                         eqi, eqj = i, j
2025-07-02 06:41:19.078                     continue
2025-07-02 06:41:19.078                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.078                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.078                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.078                 # compares by a factor of 3.
2025-07-02 06:41:19.078                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.078                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.078                 # of the computation is cached by cruncher
2025-07-02 06:41:19.078                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.078                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.078                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.078                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.078         if best_ratio < cutoff:
2025-07-02 06:41:19.078             # no non-identical "pretty close" pair
2025-07-02 06:41:19.078             if eqi is None:
2025-07-02 06:41:19.079                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.079                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.079                 return
2025-07-02 06:41:19.079             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.079             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.079         else:
2025-07-02 06:41:19.079             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.079             eqi = None
2025-07-02 06:41:19.079
2025-07-02 06:41:19.079         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.079         # identical
2025-07-02 06:41:19.079
2025-07-02 06:41:19.079         # pump out diffs from before the synch point
2025-07-02 06:41:19.079         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.079
2025-07-02 06:41:19.079         # do intraline marking on the synch pair
2025-07-02 06:41:19.079         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.079         if eqi is None:
2025-07-02 06:41:19.080             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.080             atags = btags = ""
2025-07-02 06:41:19.080             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.080             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.080                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.080                 if tag == 'replace':
2025-07-02 06:41:19.080                     atags += '^' * la
2025-07-02 06:41:19.080                     btags += '^' * lb
2025-07-02 06:41:19.080                 elif tag == 'delete':
2025-07-02 06:41:19.080                     atags += '-' * la
2025-07-02 06:41:19.080                 elif tag == 'insert':
2025-07-02 06:41:19.080                     btags += '+' * lb
2025-07-02 06:41:19.080                 elif tag == 'equal':
2025-07-02 06:41:19.080                     atags += ' ' * la
2025-07-02 06:41:19.080                     btags += ' ' * lb
2025-07-02 06:41:19.080                 else:
2025-07-02 06:41:19.080                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.080             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.080         else:
2025-07-02 06:41:19.080             # the synch pair is identical
2025-07-02 06:41:19.081             yield '  ' + aelt
2025-07-02 06:41:19.081
2025-07-02 06:41:19.081         # pump out diffs from after the synch point
2025-07-02 06:41:19.081 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.081
2025-07-02 06:41:19.081 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.081 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.081
2025-07-02 06:41:19.081 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.081 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.081 alo = 510, ahi = 1101
2025-07-02 06:41:19.081 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.081 blo = 510, bhi = 1101
2025-07-02 06:41:19.081
2025-07-02 06:41:19.081     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.081         g = []
2025-07-02 06:41:19.081         if alo < ahi:
2025-07-02 06:41:19.081             if blo < bhi:
2025-07-02 06:41:19.081                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.082             else:
2025-07-02 06:41:19.082                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.082         elif blo < bhi:
2025-07-02 06:41:19.082             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.082
2025-07-02 06:41:19.082 >       yield from g
2025-07-02 06:41:19.082
2025-07-02 06:41:19.082 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.082 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.082
2025-07-02 06:41:19.082 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.082 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.082 alo = 510, ahi = 1101
2025-07-02 06:41:19.082 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.082 blo = 510, bhi = 1101
2025-07-02 06:41:19.082
2025-07-02 06:41:19.082     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.082         r"""
2025-07-02 06:41:19.082         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.082         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.083         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.083         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.083
2025-07-02 06:41:19.083         Example:
2025-07-02 06:41:19.083
2025-07-02 06:41:19.083         >>> d = Differ()
2025-07-02 06:41:19.083         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.083         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.083         >>> print(''.join(results), end="")
2025-07-02 06:41:19.083         - abcDefghiJkl
2025-07-02 06:41:19.083         + abcdefGhijkl
2025-07-02 06:41:19.083         """
2025-07-02 06:41:19.083
2025-07-02 06:41:19.083         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.083         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.083         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.083         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.083         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.083
2025-07-02 06:41:19.084         # search for the pair that matches best without being identical
2025-07-02 06:41:19.084         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.084         # on junk -- unless we have to)
2025-07-02 06:41:19.084         for j in range(blo, bhi):
2025-07-02 06:41:19.084             bj = b[j]
2025-07-02 06:41:19.084             cruncher.set_seq2(bj)
2025-07-02 06:41:19.084             for i in range(alo, ahi):
2025-07-02 06:41:19.084                 ai = a[i]
2025-07-02 06:41:19.084                 if ai == bj:
2025-07-02 06:41:19.084                     if eqi is None:
2025-07-02 06:41:19.084                         eqi, eqj = i, j
2025-07-02 06:41:19.084                     continue
2025-07-02 06:41:19.084                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.084                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.084                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.084                 # compares by a factor of 3.
2025-07-02 06:41:19.084                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.084                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.084                 # of the computation is cached by cruncher
2025-07-02 06:41:19.085                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.085                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.085                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.085                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.085         if best_ratio < cutoff:
2025-07-02 06:41:19.085             # no non-identical "pretty close" pair
2025-07-02 06:41:19.085             if eqi is None:
2025-07-02 06:41:19.085                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.085                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.085                 return
2025-07-02 06:41:19.085             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.085             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.085         else:
2025-07-02 06:41:19.085             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.085             eqi = None
2025-07-02 06:41:19.085
2025-07-02 06:41:19.085         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.085         # identical
2025-07-02 06:41:19.085
2025-07-02 06:41:19.085         # pump out diffs from before the synch point
2025-07-02 06:41:19.086         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.086
2025-07-02 06:41:19.086         # do intraline marking on the synch pair
2025-07-02 06:41:19.086         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.086         if eqi is None:
2025-07-02 06:41:19.086             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.086             atags = btags = ""
2025-07-02 06:41:19.086             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.086             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.086                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.086                 if tag == 'replace':
2025-07-02 06:41:19.086                     atags += '^' * la
2025-07-02 06:41:19.086                     btags += '^' * lb
2025-07-02 06:41:19.086                 elif tag == 'delete':
2025-07-02 06:41:19.086                     atags += '-' * la
2025-07-02 06:41:19.086                 elif tag == 'insert':
2025-07-02 06:41:19.086                     btags += '+' * lb
2025-07-02 06:41:19.086                 elif tag == 'equal':
2025-07-02 06:41:19.086                     atags += ' ' * la
2025-07-02 06:41:19.087                     btags += ' ' * lb
2025-07-02 06:41:19.087                 else:
2025-07-02 06:41:19.087                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.087             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.087         else:
2025-07-02 06:41:19.087             # the synch pair is identical
2025-07-02 06:41:19.087             yield '  ' + aelt
2025-07-02 06:41:19.087
2025-07-02 06:41:19.087         # pump out diffs from after the synch point
2025-07-02 06:41:19.087 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.087
2025-07-02 06:41:19.087 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.087 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.087
2025-07-02 06:41:19.087 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.087 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.087 alo = 511, ahi = 1101
2025-07-02 06:41:19.087 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.087 blo = 511, bhi = 1101
2025-07-02 06:41:19.087
2025-07-02 06:41:19.088     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.088         g = []
2025-07-02 06:41:19.088         if alo < ahi:
2025-07-02 06:41:19.088             if blo < bhi:
2025-07-02 06:41:19.088                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.088             else:
2025-07-02 06:41:19.088                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.088         elif blo < bhi:
2025-07-02 06:41:19.088             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.088
2025-07-02 06:41:19.088 >       yield from g
2025-07-02 06:41:19.088
2025-07-02 06:41:19.088 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.088 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.088
2025-07-02 06:41:19.088 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.088 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.088 alo = 511, ahi = 1101
2025-07-02 06:41:19.088 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.089 blo = 511, bhi = 1101
2025-07-02 06:41:19.089
2025-07-02 06:41:19.089     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.089         r"""
2025-07-02 06:41:19.089         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.089         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.089         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.089         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.089
2025-07-02 06:41:19.089         Example:
2025-07-02 06:41:19.089
2025-07-02 06:41:19.089         >>> d = Differ()
2025-07-02 06:41:19.089         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.089         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.089         >>> print(''.join(results), end="")
2025-07-02 06:41:19.089         - abcDefghiJkl
2025-07-02 06:41:19.090         + abcdefGhijkl
2025-07-02 06:41:19.090         """
2025-07-02 06:41:19.090
2025-07-02 06:41:19.090         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.090         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.090         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.090         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.090         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.090
2025-07-02 06:41:19.090         # search for the pair that matches best without being identical
2025-07-02 06:41:19.090         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.090         # on junk -- unless we have to)
2025-07-02 06:41:19.090         for j in range(blo, bhi):
2025-07-02 06:41:19.090             bj = b[j]
2025-07-02 06:41:19.090             cruncher.set_seq2(bj)
2025-07-02 06:41:19.090             for i in range(alo, ahi):
2025-07-02 06:41:19.090                 ai = a[i]
2025-07-02 06:41:19.090                 if ai == bj:
2025-07-02 06:41:19.091                     if eqi is None:
2025-07-02 06:41:19.091                         eqi, eqj = i, j
2025-07-02 06:41:19.091                     continue
2025-07-02 06:41:19.091                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.091                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.091                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.091                 # compares by a factor of 3.
2025-07-02 06:41:19.091                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.091                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.091                 # of the computation is cached by cruncher
2025-07-02 06:41:19.091                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.091                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.091                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.091                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.091         if best_ratio < cutoff:
2025-07-02 06:41:19.091             # no non-identical "pretty close" pair
2025-07-02 06:41:19.091             if eqi is None:
2025-07-02 06:41:19.091                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.091                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.091                 return
2025-07-02 06:41:19.092             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.092             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.092         else:
2025-07-02 06:41:19.092             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.092             eqi = None
2025-07-02 06:41:19.092
2025-07-02 06:41:19.092         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.092         # identical
2025-07-02 06:41:19.092
2025-07-02 06:41:19.092         # pump out diffs from before the synch point
2025-07-02 06:41:19.092         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.092
2025-07-02 06:41:19.092         # do intraline marking on the synch pair
2025-07-02 06:41:19.092         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.092         if eqi is None:
2025-07-02 06:41:19.092             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.092             atags = btags = ""
2025-07-02 06:41:19.092             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.092             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.092                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.093                 if tag == 'replace':
2025-07-02 06:41:19.093                     atags += '^' * la
2025-07-02 06:41:19.093                     btags += '^' * lb
2025-07-02 06:41:19.093                 elif tag == 'delete':
2025-07-02 06:41:19.093                     atags += '-' * la
2025-07-02 06:41:19.093                 elif tag == 'insert':
2025-07-02 06:41:19.093                     btags += '+' * lb
2025-07-02 06:41:19.093                 elif tag == 'equal':
2025-07-02 06:41:19.093                     atags += ' ' * la
2025-07-02 06:41:19.093                     btags += ' ' * lb
2025-07-02 06:41:19.093                 else:
2025-07-02 06:41:19.093                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.093             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.093         else:
2025-07-02 06:41:19.093             # the synch pair is identical
2025-07-02 06:41:19.093             yield '  ' + aelt
2025-07-02 06:41:19.093
2025-07-02 06:41:19.093         # pump out diffs from after the synch point
2025-07-02 06:41:19.093 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.093
2025-07-02 06:41:19.093 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.094 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.094
2025-07-02 06:41:19.094 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.094 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.094 alo = 512, ahi = 1101
2025-07-02 06:41:19.094 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.094 blo = 512, bhi = 1101
2025-07-02 06:41:19.094
2025-07-02 06:41:19.094     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.094         g = []
2025-07-02 06:41:19.094         if alo < ahi:
2025-07-02 06:41:19.094             if blo < bhi:
2025-07-02 06:41:19.094                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.094             else:
2025-07-02 06:41:19.094                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.094         elif blo < bhi:
2025-07-02 06:41:19.094             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.094
2025-07-02 06:41:19.094 >       yield from g
2025-07-02 06:41:19.094
2025-07-02 06:41:19.095 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.095 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.095
2025-07-02 06:41:19.095 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.095 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.095 alo = 512, ahi = 1101
2025-07-02 06:41:19.095 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.095 blo = 512, bhi = 1101
2025-07-02 06:41:19.095
2025-07-02 06:41:19.095     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.095         r"""
2025-07-02 06:41:19.095         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.095         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.095         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.095         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.095
2025-07-02 06:41:19.095         Example:
2025-07-02 06:41:19.095
2025-07-02 06:41:19.095         >>> d = Differ()
2025-07-02 06:41:19.095         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.096         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.096         >>> print(''.join(results), end="")
2025-07-02 06:41:19.096         - abcDefghiJkl
2025-07-02 06:41:19.096         + abcdefGhijkl
2025-07-02 06:41:19.096         """
2025-07-02 06:41:19.096
2025-07-02 06:41:19.096         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.096         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.096         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.096         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.096         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.096
2025-07-02 06:41:19.096         # search for the pair that matches best without being identical
2025-07-02 06:41:19.096         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.096         # on junk -- unless we have to)
2025-07-02 06:41:19.096         for j in range(blo, bhi):
2025-07-02 06:41:19.096             bj = b[j]
2025-07-02 06:41:19.096             cruncher.set_seq2(bj)
2025-07-02 06:41:19.097             for i in range(alo, ahi):
2025-07-02 06:41:19.097                 ai = a[i]
2025-07-02 06:41:19.097                 if ai == bj:
2025-07-02 06:41:19.097                     if eqi is None:
2025-07-02 06:41:19.097                         eqi, eqj = i, j
2025-07-02 06:41:19.097                     continue
2025-07-02 06:41:19.097                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.097                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.097                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.097                 # compares by a factor of 3.
2025-07-02 06:41:19.097                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.097                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.097                 # of the computation is cached by cruncher
2025-07-02 06:41:19.097                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.097                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.097                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.097                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.097         if best_ratio < cutoff:
2025-07-02 06:41:19.097             # no non-identical "pretty close" pair
2025-07-02 06:41:19.098             if eqi is None:
2025-07-02 06:41:19.098                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.098                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.098                 return
2025-07-02 06:41:19.098             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.098             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.098         else:
2025-07-02 06:41:19.098             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.098             eqi = None
2025-07-02 06:41:19.098
2025-07-02 06:41:19.098         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.098         # identical
2025-07-02 06:41:19.098
2025-07-02 06:41:19.098         # pump out diffs from before the synch point
2025-07-02 06:41:19.098         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.098
2025-07-02 06:41:19.098         # do intraline marking on the synch pair
2025-07-02 06:41:19.098         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.098         if eqi is None:
2025-07-02 06:41:19.099             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.099             atags = btags = ""
2025-07-02 06:41:19.099             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.099             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.099                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.099                 if tag == 'replace':
2025-07-02 06:41:19.099                     atags += '^' * la
2025-07-02 06:41:19.099                     btags += '^' * lb
2025-07-02 06:41:19.099                 elif tag == 'delete':
2025-07-02 06:41:19.099                     atags += '-' * la
2025-07-02 06:41:19.099                 elif tag == 'insert':
2025-07-02 06:41:19.099                     btags += '+' * lb
2025-07-02 06:41:19.099                 elif tag == 'equal':
2025-07-02 06:41:19.099                     atags += ' ' * la
2025-07-02 06:41:19.099                     btags += ' ' * lb
2025-07-02 06:41:19.099                 else:
2025-07-02 06:41:19.099                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.099             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.099         else:
2025-07-02 06:41:19.099             # the synch pair is identical
2025-07-02 06:41:19.099             yield '  ' + aelt
2025-07-02 06:41:19.100
2025-07-02 06:41:19.100         # pump out diffs from after the synch point
2025-07-02 06:41:19.100 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.100
2025-07-02 06:41:19.100 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.100
2025-07-02 06:41:19.100 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.100 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.100 alo = 513, ahi = 1101
2025-07-02 06:41:19.100 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.100 blo = 513, bhi = 1101
2025-07-02 06:41:19.100
2025-07-02 06:41:19.100     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.100         g = []
2025-07-02 06:41:19.100         if alo < ahi:
2025-07-02 06:41:19.100             if blo < bhi:
2025-07-02 06:41:19.100                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.101             else:
2025-07-02 06:41:19.101                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.101         elif blo < bhi:
2025-07-02 06:41:19.101             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.101
2025-07-02 06:41:19.101 >       yield from g
2025-07-02 06:41:19.101
2025-07-02 06:41:19.101 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.101 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.101
2025-07-02 06:41:19.101 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.101 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.101 alo = 513, ahi = 1101
2025-07-02 06:41:19.101 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.101 blo = 513, bhi = 1101
2025-07-02 06:41:19.101
2025-07-02 06:41:19.101     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.101         r"""
2025-07-02 06:41:19.101         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.102         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.102         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.102         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.102
2025-07-02 06:41:19.102         Example:
2025-07-02 06:41:19.102
2025-07-02 06:41:19.102         >>> d = Differ()
2025-07-02 06:41:19.102         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.102         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.102         >>> print(''.join(results), end="")
2025-07-02 06:41:19.102         - abcDefghiJkl
2025-07-02 06:41:19.102         + abcdefGhijkl
2025-07-02 06:41:19.102         """
2025-07-02 06:41:19.102
2025-07-02 06:41:19.102         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.102         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.102         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.102         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.103         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.103
2025-07-02 06:41:19.103         # search for the pair that matches best without being identical
2025-07-02 06:41:19.103         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.103         # on junk -- unless we have to)
2025-07-02 06:41:19.103         for j in range(blo, bhi):
2025-07-02 06:41:19.103             bj = b[j]
2025-07-02 06:41:19.103             cruncher.set_seq2(bj)
2025-07-02 06:41:19.103             for i in range(alo, ahi):
2025-07-02 06:41:19.103                 ai = a[i]
2025-07-02 06:41:19.103                 if ai == bj:
2025-07-02 06:41:19.103                     if eqi is None:
2025-07-02 06:41:19.103                         eqi, eqj = i, j
2025-07-02 06:41:19.103                     continue
2025-07-02 06:41:19.103                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.103                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.103                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.103                 # compares by a factor of 3.
2025-07-02 06:41:19.103                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.103                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.104                 # of the computation is cached by cruncher
2025-07-02 06:41:19.104                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.104                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.104                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.104                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.104         if best_ratio < cutoff:
2025-07-02 06:41:19.104             # no non-identical "pretty close" pair
2025-07-02 06:41:19.104             if eqi is None:
2025-07-02 06:41:19.104                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.104                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.104                 return
2025-07-02 06:41:19.104             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.104             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.104         else:
2025-07-02 06:41:19.104             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.104             eqi = None
2025-07-02 06:41:19.104
2025-07-02 06:41:19.104         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.104         # identical
2025-07-02 06:41:19.104
2025-07-02 06:41:19.104         # pump out diffs from before the synch point
2025-07-02 06:41:19.105         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.105
2025-07-02 06:41:19.105         # do intraline marking on the synch pair
2025-07-02 06:41:19.105         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.105         if eqi is None:
2025-07-02 06:41:19.105             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.105             atags = btags = ""
2025-07-02 06:41:19.105             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.105             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.105                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.105                 if tag == 'replace':
2025-07-02 06:41:19.105                     atags += '^' * la
2025-07-02 06:41:19.105                     btags += '^' * lb
2025-07-02 06:41:19.105                 elif tag == 'delete':
2025-07-02 06:41:19.105                     atags += '-' * la
2025-07-02 06:41:19.105                 elif tag == 'insert':
2025-07-02 06:41:19.105                     btags += '+' * lb
2025-07-02 06:41:19.105                 elif tag == 'equal':
2025-07-02 06:41:19.106                     atags += ' ' * la
2025-07-02 06:41:19.106                     btags += ' ' * lb
2025-07-02 06:41:19.106                 else:
2025-07-02 06:41:19.106                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.106             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.106         else:
2025-07-02 06:41:19.106             # the synch pair is identical
2025-07-02 06:41:19.106             yield '  ' + aelt
2025-07-02 06:41:19.106
2025-07-02 06:41:19.106         # pump out diffs from after the synch point
2025-07-02 06:41:19.106 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.106
2025-07-02 06:41:19.106 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.106 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.106
2025-07-02 06:41:19.106 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.106 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.106 alo = 514, ahi = 1101
2025-07-02 06:41:19.106 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.107 blo = 514, bhi = 1101
2025-07-02 06:41:19.107
2025-07-02 06:41:19.107     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.107         g = []
2025-07-02 06:41:19.107         if alo < ahi:
2025-07-02 06:41:19.107             if blo < bhi:
2025-07-02 06:41:19.107                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.107             else:
2025-07-02 06:41:19.107                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.107         elif blo < bhi:
2025-07-02 06:41:19.107             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.107
2025-07-02 06:41:19.107 >       yield from g
2025-07-02 06:41:19.107
2025-07-02 06:41:19.107 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.107 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.107
2025-07-02 06:41:19.107 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.107 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.108 alo = 514, ahi = 1101
2025-07-02 06:41:19.108 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.108 blo = 514, bhi = 1101
2025-07-02 06:41:19.108
2025-07-02 06:41:19.108     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.108         r"""
2025-07-02 06:41:19.108         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.108         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.108         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.108         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.108
2025-07-02 06:41:19.108         Example:
2025-07-02 06:41:19.108
2025-07-02 06:41:19.108         >>> d = Differ()
2025-07-02 06:41:19.108         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.108         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.108         >>> print(''.join(results), end="")
2025-07-02 06:41:19.108         - abcDefghiJkl
2025-07-02 06:41:19.108         + abcdefGhijkl
2025-07-02 06:41:19.109         """
2025-07-02 06:41:19.109
2025-07-02 06:41:19.109         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.109         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.109         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.109         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.109         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.109
2025-07-02 06:41:19.109         # search for the pair that matches best without being identical
2025-07-02 06:41:19.109         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.109         # on junk -- unless we have to)
2025-07-02 06:41:19.109         for j in range(blo, bhi):
2025-07-02 06:41:19.109             bj = b[j]
2025-07-02 06:41:19.109             cruncher.set_seq2(bj)
2025-07-02 06:41:19.109             for i in range(alo, ahi):
2025-07-02 06:41:19.109                 ai = a[i]
2025-07-02 06:41:19.109                 if ai == bj:
2025-07-02 06:41:19.109                     if eqi is None:
2025-07-02 06:41:19.109                         eqi, eqj = i, j
2025-07-02 06:41:19.109                     continue
2025-07-02 06:41:19.110                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.110                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.110                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.110                 # compares by a factor of 3.
2025-07-02 06:41:19.110                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.110                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.110                 # of the computation is cached by cruncher
2025-07-02 06:41:19.110                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.110                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.110                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.110                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.110         if best_ratio < cutoff:
2025-07-02 06:41:19.110             # no non-identical "pretty close" pair
2025-07-02 06:41:19.110             if eqi is None:
2025-07-02 06:41:19.110                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.110                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.110                 return
2025-07-02 06:41:19.110             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.110             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.110         else:
2025-07-02 06:41:19.111             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.111             eqi = None
2025-07-02 06:41:19.111
2025-07-02 06:41:19.111         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.111         # identical
2025-07-02 06:41:19.111
2025-07-02 06:41:19.111         # pump out diffs from before the synch point
2025-07-02 06:41:19.111         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.111
2025-07-02 06:41:19.111         # do intraline marking on the synch pair
2025-07-02 06:41:19.111         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.111         if eqi is None:
2025-07-02 06:41:19.111             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.111             atags = btags = ""
2025-07-02 06:41:19.111             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.111             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.111                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.111                 if tag == 'replace':
2025-07-02 06:41:19.111                     atags += '^' * la
2025-07-02 06:41:19.111                     btags += '^' * lb
2025-07-02 06:41:19.112                 elif tag == 'delete':
2025-07-02 06:41:19.112                     atags += '-' * la
2025-07-02 06:41:19.112                 elif tag == 'insert':
2025-07-02 06:41:19.112                     btags += '+' * lb
2025-07-02 06:41:19.112                 elif tag == 'equal':
2025-07-02 06:41:19.112                     atags += ' ' * la
2025-07-02 06:41:19.112                     btags += ' ' * lb
2025-07-02 06:41:19.112                 else:
2025-07-02 06:41:19.112                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.112             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.112         else:
2025-07-02 06:41:19.112             # the synch pair is identical
2025-07-02 06:41:19.112             yield '  ' + aelt
2025-07-02 06:41:19.112
2025-07-02 06:41:19.112         # pump out diffs from after the synch point
2025-07-02 06:41:19.112 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.112
2025-07-02 06:41:19.112 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.112 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.113
2025-07-02 06:41:19.113 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.113 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.113 alo = 515, ahi = 1101
2025-07-02 06:41:19.113 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.113 blo = 515, bhi = 1101
2025-07-02 06:41:19.113
2025-07-02 06:41:19.113     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.113         g = []
2025-07-02 06:41:19.113         if alo < ahi:
2025-07-02 06:41:19.113             if blo < bhi:
2025-07-02 06:41:19.113                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.113             else:
2025-07-02 06:41:19.113                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.113         elif blo < bhi:
2025-07-02 06:41:19.113             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.113
2025-07-02 06:41:19.113 >       yield from g
2025-07-02 06:41:19.113
2025-07-02 06:41:19.113 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.114 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.114
2025-07-02 06:41:19.114 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.114 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.114 alo = 515, ahi = 1101
2025-07-02 06:41:19.114 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.114 blo = 515, bhi = 1101
2025-07-02 06:41:19.114
2025-07-02 06:41:19.114     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.114         r"""
2025-07-02 06:41:19.114         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.114         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.114         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.114         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.114
2025-07-02 06:41:19.114         Example:
2025-07-02 06:41:19.114
2025-07-02 06:41:19.114         >>> d = Differ()
2025-07-02 06:41:19.115         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.115         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.115         >>> print(''.join(results), end="")
2025-07-02 06:41:19.115         - abcDefghiJkl
2025-07-02 06:41:19.115         + abcdefGhijkl
2025-07-02 06:41:19.115         """
2025-07-02 06:41:19.115
2025-07-02 06:41:19.115         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.115         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.115         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.115         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.115         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.115
2025-07-02 06:41:19.115         # search for the pair that matches best without being identical
2025-07-02 06:41:19.115         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.115         # on junk -- unless we have to)
2025-07-02 06:41:19.116         for j in range(blo, bhi):
2025-07-02 06:41:19.116             bj = b[j]
2025-07-02 06:41:19.116             cruncher.set_seq2(bj)
2025-07-02 06:41:19.116             for i in range(alo, ahi):
2025-07-02 06:41:19.116                 ai = a[i]
2025-07-02 06:41:19.116                 if ai == bj:
2025-07-02 06:41:19.116                     if eqi is None:
2025-07-02 06:41:19.116                         eqi, eqj = i, j
2025-07-02 06:41:19.116                     continue
2025-07-02 06:41:19.116                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.116                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.116                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.116                 # compares by a factor of 3.
2025-07-02 06:41:19.116                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.116                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.116                 # of the computation is cached by cruncher
2025-07-02 06:41:19.116                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.116                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.116                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.117                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.117         if best_ratio < cutoff:
2025-07-02 06:41:19.117             # no non-identical "pretty close" pair
2025-07-02 06:41:19.117             if eqi is None:
2025-07-02 06:41:19.117                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.117                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.117                 return
2025-07-02 06:41:19.117             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.117             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.117         else:
2025-07-02 06:41:19.117             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.117             eqi = None
2025-07-02 06:41:19.117
2025-07-02 06:41:19.117         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.117         # identical
2025-07-02 06:41:19.117
2025-07-02 06:41:19.117         # pump out diffs from before the synch point
2025-07-02 06:41:19.117         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.117
2025-07-02 06:41:19.117         # do intraline marking on the synch pair
2025-07-02 06:41:19.118         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.118         if eqi is None:
2025-07-02 06:41:19.118             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.118             atags = btags = ""
2025-07-02 06:41:19.118             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.118             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.118                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.118                 if tag == 'replace':
2025-07-02 06:41:19.118                     atags += '^' * la
2025-07-02 06:41:19.118                     btags += '^' * lb
2025-07-02 06:41:19.118                 elif tag == 'delete':
2025-07-02 06:41:19.118                     atags += '-' * la
2025-07-02 06:41:19.118                 elif tag == 'insert':
2025-07-02 06:41:19.118                     btags += '+' * lb
2025-07-02 06:41:19.118                 elif tag == 'equal':
2025-07-02 06:41:19.118                     atags += ' ' * la
2025-07-02 06:41:19.118                     btags += ' ' * lb
2025-07-02 06:41:19.118                 else:
2025-07-02 06:41:19.118                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.118             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.119         else:
2025-07-02 06:41:19.119             # the synch pair is identical
2025-07-02 06:41:19.119             yield '  ' + aelt
2025-07-02 06:41:19.119
2025-07-02 06:41:19.119         # pump out diffs from after the synch point
2025-07-02 06:41:19.119 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.119
2025-07-02 06:41:19.119 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.119 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.119
2025-07-02 06:41:19.119 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.119 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.119 alo = 516, ahi = 1101
2025-07-02 06:41:19.119 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.119 blo = 516, bhi = 1101
2025-07-02 06:41:19.119
2025-07-02 06:41:19.119     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.119         g = []
2025-07-02 06:41:19.119         if alo < ahi:
2025-07-02 06:41:19.119             if blo < bhi:
2025-07-02 06:41:19.120                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.120             else:
2025-07-02 06:41:19.120                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.120         elif blo < bhi:
2025-07-02 06:41:19.120             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.120
2025-07-02 06:41:19.120 >       yield from g
2025-07-02 06:41:19.120
2025-07-02 06:41:19.120 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.120 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.120
2025-07-02 06:41:19.120 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.120 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.120 alo = 516, ahi = 1101
2025-07-02 06:41:19.120 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.120 blo = 516, bhi = 1101
2025-07-02 06:41:19.120
2025-07-02 06:41:19.120     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.120         r"""
2025-07-02 06:41:19.120         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.121         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.121         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.121         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.121
2025-07-02 06:41:19.121         Example:
2025-07-02 06:41:19.121
2025-07-02 06:41:19.121         >>> d = Differ()
2025-07-02 06:41:19.121         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.121         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.121         >>> print(''.join(results), end="")
2025-07-02 06:41:19.121         - abcDefghiJkl
2025-07-02 06:41:19.121         + abcdefGhijkl
2025-07-02 06:41:19.121         """
2025-07-02 06:41:19.121
2025-07-02 06:41:19.121         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.121         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.121         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.121         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.122         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.122
2025-07-02 06:41:19.122         # search for the pair that matches best without being identical
2025-07-02 06:41:19.122         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.122         # on junk -- unless we have to)
2025-07-02 06:41:19.122         for j in range(blo, bhi):
2025-07-02 06:41:19.122             bj = b[j]
2025-07-02 06:41:19.122             cruncher.set_seq2(bj)
2025-07-02 06:41:19.122             for i in range(alo, ahi):
2025-07-02 06:41:19.122                 ai = a[i]
2025-07-02 06:41:19.122                 if ai == bj:
2025-07-02 06:41:19.122                     if eqi is None:
2025-07-02 06:41:19.122                         eqi, eqj = i, j
2025-07-02 06:41:19.122                     continue
2025-07-02 06:41:19.122                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.122                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.122                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.122                 # compares by a factor of 3.
2025-07-02 06:41:19.122                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.123                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.123                 # of the computation is cached by cruncher
2025-07-02 06:41:19.123                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.123                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.123                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.123                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.123         if best_ratio < cutoff:
2025-07-02 06:41:19.123             # no non-identical "pretty close" pair
2025-07-02 06:41:19.123             if eqi is None:
2025-07-02 06:41:19.123                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.123                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.123                 return
2025-07-02 06:41:19.123             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.123             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.123         else:
2025-07-02 06:41:19.123             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.123             eqi = None
2025-07-02 06:41:19.123
2025-07-02 06:41:19.124         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.124         # identical
2025-07-02 06:41:19.124
2025-07-02 06:41:19.124         # pump out diffs from before the synch point
2025-07-02 06:41:19.124         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.124
2025-07-02 06:41:19.124         # do intraline marking on the synch pair
2025-07-02 06:41:19.124         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.124         if eqi is None:
2025-07-02 06:41:19.124             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.124             atags = btags = ""
2025-07-02 06:41:19.124             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.124             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.124                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.124                 if tag == 'replace':
2025-07-02 06:41:19.124                     atags += '^' * la
2025-07-02 06:41:19.124                     btags += '^' * lb
2025-07-02 06:41:19.124                 elif tag == 'delete':
2025-07-02 06:41:19.124                     atags += '-' * la
2025-07-02 06:41:19.124                 elif tag == 'insert':
2025-07-02 06:41:19.125                     btags += '+' * lb
2025-07-02 06:41:19.125                 elif tag == 'equal':
2025-07-02 06:41:19.125                     atags += ' ' * la
2025-07-02 06:41:19.125                     btags += ' ' * lb
2025-07-02 06:41:19.125                 else:
2025-07-02 06:41:19.125                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.125             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.125         else:
2025-07-02 06:41:19.125             # the synch pair is identical
2025-07-02 06:41:19.125             yield '  ' + aelt
2025-07-02 06:41:19.125
2025-07-02 06:41:19.125         # pump out diffs from after the synch point
2025-07-02 06:41:19.125 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.125
2025-07-02 06:41:19.125 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.125 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.125
2025-07-02 06:41:19.125 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.125 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.126 alo = 517, ahi = 1101
2025-07-02 06:41:19.126 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.126 blo = 517, bhi = 1101
2025-07-02 06:41:19.126
2025-07-02 06:41:19.126     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.126         g = []
2025-07-02 06:41:19.126         if alo < ahi:
2025-07-02 06:41:19.126             if blo < bhi:
2025-07-02 06:41:19.126                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.126             else:
2025-07-02 06:41:19.126                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.126         elif blo < bhi:
2025-07-02 06:41:19.126             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.126
2025-07-02 06:41:19.126 >       yield from g
2025-07-02 06:41:19.126
2025-07-02 06:41:19.126 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.126 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.126
2025-07-02 06:41:19.126 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.127 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.127 alo = 517, ahi = 1101
2025-07-02 06:41:19.127 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.127 blo = 517, bhi = 1101
2025-07-02 06:41:19.127
2025-07-02 06:41:19.127     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.127         r"""
2025-07-02 06:41:19.127         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.127         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.127         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.127         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.127
2025-07-02 06:41:19.127         Example:
2025-07-02 06:41:19.127
2025-07-02 06:41:19.127         >>> d = Differ()
2025-07-02 06:41:19.127         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.127         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.127         >>> print(''.join(results), end="")
2025-07-02 06:41:19.127         - abcDefghiJkl
2025-07-02 06:41:19.128         + abcdefGhijkl
2025-07-02 06:41:19.128         """
2025-07-02 06:41:19.128
2025-07-02 06:41:19.128         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.128         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.128         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.128         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.128         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.128
2025-07-02 06:41:19.128         # search for the pair that matches best without being identical
2025-07-02 06:41:19.128         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.128         # on junk -- unless we have to)
2025-07-02 06:41:19.128         for j in range(blo, bhi):
2025-07-02 06:41:19.128             bj = b[j]
2025-07-02 06:41:19.128             cruncher.set_seq2(bj)
2025-07-02 06:41:19.128             for i in range(alo, ahi):
2025-07-02 06:41:19.128                 ai = a[i]
2025-07-02 06:41:19.128                 if ai == bj:
2025-07-02 06:41:19.128                     if eqi is None:
2025-07-02 06:41:19.128                         eqi, eqj = i, j
2025-07-02 06:41:19.129                     continue
2025-07-02 06:41:19.129                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.129                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.129                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.129                 # compares by a factor of 3.
2025-07-02 06:41:19.129                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.129                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.129                 # of the computation is cached by cruncher
2025-07-02 06:41:19.129                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.129                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.129                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.129                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.129         if best_ratio < cutoff:
2025-07-02 06:41:19.129             # no non-identical "pretty close" pair
2025-07-02 06:41:19.129             if eqi is None:
2025-07-02 06:41:19.129                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.129                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.129                 return
2025-07-02 06:41:19.129             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.129             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.130         else:
2025-07-02 06:41:19.130             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.130             eqi = None
2025-07-02 06:41:19.130
2025-07-02 06:41:19.130         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.130         # identical
2025-07-02 06:41:19.130
2025-07-02 06:41:19.130         # pump out diffs from before the synch point
2025-07-02 06:41:19.130         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.130
2025-07-02 06:41:19.130         # do intraline marking on the synch pair
2025-07-02 06:41:19.130         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.130         if eqi is None:
2025-07-02 06:41:19.130             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.130             atags = btags = ""
2025-07-02 06:41:19.130             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.130             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.130                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.130                 if tag == 'replace':
2025-07-02 06:41:19.130                     atags += '^' * la
2025-07-02 06:41:19.131                     btags += '^' * lb
2025-07-02 06:41:19.131                 elif tag == 'delete':
2025-07-02 06:41:19.131                     atags += '-' * la
2025-07-02 06:41:19.131                 elif tag == 'insert':
2025-07-02 06:41:19.131                     btags += '+' * lb
2025-07-02 06:41:19.131                 elif tag == 'equal':
2025-07-02 06:41:19.131                     atags += ' ' * la
2025-07-02 06:41:19.131                     btags += ' ' * lb
2025-07-02 06:41:19.131                 else:
2025-07-02 06:41:19.131                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.131             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.131         else:
2025-07-02 06:41:19.131             # the synch pair is identical
2025-07-02 06:41:19.131             yield '  ' + aelt
2025-07-02 06:41:19.131
2025-07-02 06:41:19.131         # pump out diffs from after the synch point
2025-07-02 06:41:19.131 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.131
2025-07-02 06:41:19.132 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.132 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.132
2025-07-02 06:41:19.132 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.132 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.132 alo = 518, ahi = 1101
2025-07-02 06:41:19.132 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.132 blo = 518, bhi = 1101
2025-07-02 06:41:19.132
2025-07-02 06:41:19.132     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.132         g = []
2025-07-02 06:41:19.132         if alo < ahi:
2025-07-02 06:41:19.132             if blo < bhi:
2025-07-02 06:41:19.132                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.132             else:
2025-07-02 06:41:19.132                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.132         elif blo < bhi:
2025-07-02 06:41:19.132             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.133
2025-07-02 06:41:19.133 >       yield from g
2025-07-02 06:41:19.133
2025-07-02 06:41:19.133 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.133 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.133
2025-07-02 06:41:19.133 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.133 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.133 alo = 518, ahi = 1101
2025-07-02 06:41:19.133 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.133 blo = 518, bhi = 1101
2025-07-02 06:41:19.133
2025-07-02 06:41:19.133     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.133         r"""
2025-07-02 06:41:19.133         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.133         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.133         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.133         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.133
2025-07-02 06:41:19.134         Example:
2025-07-02 06:41:19.134
2025-07-02 06:41:19.134         >>> d = Differ()
2025-07-02 06:41:19.134         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.134         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.134         >>> print(''.join(results), end="")
2025-07-02 06:41:19.134         - abcDefghiJkl
2025-07-02 06:41:19.134         + abcdefGhijkl
2025-07-02 06:41:19.134         """
2025-07-02 06:41:19.134
2025-07-02 06:41:19.134         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.134         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.134         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.134         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.134         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.134
2025-07-02 06:41:19.134         # search for the pair that matches best without being identical
2025-07-02 06:41:19.134         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.135         # on junk -- unless we have to)
2025-07-02 06:41:19.135         for j in range(blo, bhi):
2025-07-02 06:41:19.135             bj = b[j]
2025-07-02 06:41:19.135             cruncher.set_seq2(bj)
2025-07-02 06:41:19.135             for i in range(alo, ahi):
2025-07-02 06:41:19.135                 ai = a[i]
2025-07-02 06:41:19.135                 if ai == bj:
2025-07-02 06:41:19.135                     if eqi is None:
2025-07-02 06:41:19.135                         eqi, eqj = i, j
2025-07-02 06:41:19.135                     continue
2025-07-02 06:41:19.135                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.135                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.135                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.135                 # compares by a factor of 3.
2025-07-02 06:41:19.135                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.135                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.135                 # of the computation is cached by cruncher
2025-07-02 06:41:19.135                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.135                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.136                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.136                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.136         if best_ratio < cutoff:
2025-07-02 06:41:19.136             # no non-identical "pretty close" pair
2025-07-02 06:41:19.136             if eqi is None:
2025-07-02 06:41:19.136                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.136                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.136                 return
2025-07-02 06:41:19.136             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.136             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.136         else:
2025-07-02 06:41:19.136             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.136             eqi = None
2025-07-02 06:41:19.136
2025-07-02 06:41:19.136         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.136         # identical
2025-07-02 06:41:19.136
2025-07-02 06:41:19.136         # pump out diffs from before the synch point
2025-07-02 06:41:19.136         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.137
2025-07-02 06:41:19.137         # do intraline marking on the synch pair
2025-07-02 06:41:19.137         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.137         if eqi is None:
2025-07-02 06:41:19.137             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.137             atags = btags = ""
2025-07-02 06:41:19.137             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.137             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.137                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.137                 if tag == 'replace':
2025-07-02 06:41:19.137                     atags += '^' * la
2025-07-02 06:41:19.137                     btags += '^' * lb
2025-07-02 06:41:19.137                 elif tag == 'delete':
2025-07-02 06:41:19.137                     atags += '-' * la
2025-07-02 06:41:19.137                 elif tag == 'insert':
2025-07-02 06:41:19.137                     btags += '+' * lb
2025-07-02 06:41:19.137                 elif tag == 'equal':
2025-07-02 06:41:19.137                     atags += ' ' * la
2025-07-02 06:41:19.137                     btags += ' ' * lb
2025-07-02 06:41:19.137                 else:
2025-07-02 06:41:19.138                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.138             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.138         else:
2025-07-02 06:41:19.138             # the synch pair is identical
2025-07-02 06:41:19.138             yield '  ' + aelt
2025-07-02 06:41:19.138
2025-07-02 06:41:19.138         # pump out diffs from after the synch point
2025-07-02 06:41:19.138 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.138
2025-07-02 06:41:19.138 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.138 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.138
2025-07-02 06:41:19.138 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.138 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.138 alo = 519, ahi = 1101
2025-07-02 06:41:19.138 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.138 blo = 519, bhi = 1101
2025-07-02 06:41:19.138
2025-07-02 06:41:19.138     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.138         g = []
2025-07-02 06:41:19.139         if alo < ahi:
2025-07-02 06:41:19.139             if blo < bhi:
2025-07-02 06:41:19.139                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.139             else:
2025-07-02 06:41:19.139                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.139         elif blo < bhi:
2025-07-02 06:41:19.139             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.139
2025-07-02 06:41:19.139 >       yield from g
2025-07-02 06:41:19.139
2025-07-02 06:41:19.139 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.139 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.139
2025-07-02 06:41:19.139 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.139 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.139 alo = 519, ahi = 1101
2025-07-02 06:41:19.139 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.139 blo = 519, bhi = 1101
2025-07-02 06:41:19.139
2025-07-02 06:41:19.139     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.140         r"""
2025-07-02 06:41:19.140         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.140         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.140         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.140         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.140
2025-07-02 06:41:19.140         Example:
2025-07-02 06:41:19.140
2025-07-02 06:41:19.140         >>> d = Differ()
2025-07-02 06:41:19.140         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.140         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.140         >>> print(''.join(results), end="")
2025-07-02 06:41:19.140         - abcDefghiJkl
2025-07-02 06:41:19.140         + abcdefGhijkl
2025-07-02 06:41:19.140         """
2025-07-02 06:41:19.140
2025-07-02 06:41:19.140         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.140         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.141         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.141         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.141         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.141
2025-07-02 06:41:19.141         # search for the pair that matches best without being identical
2025-07-02 06:41:19.141         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.141         # on junk -- unless we have to)
2025-07-02 06:41:19.141         for j in range(blo, bhi):
2025-07-02 06:41:19.141             bj = b[j]
2025-07-02 06:41:19.141             cruncher.set_seq2(bj)
2025-07-02 06:41:19.141             for i in range(alo, ahi):
2025-07-02 06:41:19.141                 ai = a[i]
2025-07-02 06:41:19.141                 if ai == bj:
2025-07-02 06:41:19.141                     if eqi is None:
2025-07-02 06:41:19.141                         eqi, eqj = i, j
2025-07-02 06:41:19.141                     continue
2025-07-02 06:41:19.141                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.141                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.141                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.142                 # compares by a factor of 3.
2025-07-02 06:41:19.142                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.142                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.142                 # of the computation is cached by cruncher
2025-07-02 06:41:19.142                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.142                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.142                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.142                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.142         if best_ratio < cutoff:
2025-07-02 06:41:19.142             # no non-identical "pretty close" pair
2025-07-02 06:41:19.142             if eqi is None:
2025-07-02 06:41:19.142                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.142                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.142                 return
2025-07-02 06:41:19.142             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.142             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.142         else:
2025-07-02 06:41:19.142             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.142             eqi = None
2025-07-02 06:41:19.143
2025-07-02 06:41:19.143         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.143         # identical
2025-07-02 06:41:19.143
2025-07-02 06:41:19.143         # pump out diffs from before the synch point
2025-07-02 06:41:19.143         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.143
2025-07-02 06:41:19.143         # do intraline marking on the synch pair
2025-07-02 06:41:19.143         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.143         if eqi is None:
2025-07-02 06:41:19.143             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.143             atags = btags = ""
2025-07-02 06:41:19.143             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.143             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.143                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.143                 if tag == 'replace':
2025-07-02 06:41:19.143                     atags += '^' * la
2025-07-02 06:41:19.143                     btags += '^' * lb
2025-07-02 06:41:19.143                 elif tag == 'delete':
2025-07-02 06:41:19.144                     atags += '-' * la
2025-07-02 06:41:19.144                 elif tag == 'insert':
2025-07-02 06:41:19.144                     btags += '+' * lb
2025-07-02 06:41:19.144                 elif tag == 'equal':
2025-07-02 06:41:19.144                     atags += ' ' * la
2025-07-02 06:41:19.144                     btags += ' ' * lb
2025-07-02 06:41:19.144                 else:
2025-07-02 06:41:19.144                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.144             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.144         else:
2025-07-02 06:41:19.144             # the synch pair is identical
2025-07-02 06:41:19.144             yield '  ' + aelt
2025-07-02 06:41:19.144
2025-07-02 06:41:19.144         # pump out diffs from after the synch point
2025-07-02 06:41:19.144 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.144
2025-07-02 06:41:19.144 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.144 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.144
2025-07-02 06:41:19.144 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.145 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.145 alo = 520, ahi = 1101
2025-07-02 06:41:19.145 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.145 blo = 520, bhi = 1101
2025-07-02 06:41:19.145
2025-07-02 06:41:19.145     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.145         g = []
2025-07-02 06:41:19.145         if alo < ahi:
2025-07-02 06:41:19.145             if blo < bhi:
2025-07-02 06:41:19.145                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.145             else:
2025-07-02 06:41:19.145                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.145         elif blo < bhi:
2025-07-02 06:41:19.145             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.145
2025-07-02 06:41:19.145 >       yield from g
2025-07-02 06:41:19.145
2025-07-02 06:41:19.145 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.146 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.146
2025-07-02 06:41:19.146 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.146 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.146 alo = 520, ahi = 1101
2025-07-02 06:41:19.146 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.146 blo = 520, bhi = 1101
2025-07-02 06:41:19.146
2025-07-02 06:41:19.146     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.146         r"""
2025-07-02 06:41:19.146         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.146         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.146         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.146         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.146
2025-07-02 06:41:19.146         Example:
2025-07-02 06:41:19.146
2025-07-02 06:41:19.146         >>> d = Differ()
2025-07-02 06:41:19.147         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.147         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.147         >>> print(''.join(results), end="")
2025-07-02 06:41:19.147         - abcDefghiJkl
2025-07-02 06:41:19.147         + abcdefGhijkl
2025-07-02 06:41:19.147         """
2025-07-02 06:41:19.147
2025-07-02 06:41:19.147         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.147         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.147         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.147         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.147         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.147
2025-07-02 06:41:19.147         # search for the pair that matches best without being identical
2025-07-02 06:41:19.147         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.147         # on junk -- unless we have to)
2025-07-02 06:41:19.147         for j in range(blo, bhi):
2025-07-02 06:41:19.147             bj = b[j]
2025-07-02 06:41:19.148             cruncher.set_seq2(bj)
2025-07-02 06:41:19.148             for i in range(alo, ahi):
2025-07-02 06:41:19.148                 ai = a[i]
2025-07-02 06:41:19.148                 if ai == bj:
2025-07-02 06:41:19.148                     if eqi is None:
2025-07-02 06:41:19.148                         eqi, eqj = i, j
2025-07-02 06:41:19.148                     continue
2025-07-02 06:41:19.148                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.148                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.148                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.148                 # compares by a factor of 3.
2025-07-02 06:41:19.148                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.148                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.148                 # of the computation is cached by cruncher
2025-07-02 06:41:19.148                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.148                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.148                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.148                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.148         if best_ratio < cutoff:
2025-07-02 06:41:19.148             # no non-identical "pretty close" pair
2025-07-02 06:41:19.149             if eqi is None:
2025-07-02 06:41:19.149                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.149                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.149                 return
2025-07-02 06:41:19.149             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.149             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.149         else:
2025-07-02 06:41:19.149             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.149             eqi = None
2025-07-02 06:41:19.149
2025-07-02 06:41:19.149         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.149         # identical
2025-07-02 06:41:19.149
2025-07-02 06:41:19.149         # pump out diffs from before the synch point
2025-07-02 06:41:19.149         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.149
2025-07-02 06:41:19.149         # do intraline marking on the synch pair
2025-07-02 06:41:19.149         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.149         if eqi is None:
2025-07-02 06:41:19.149             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.149             atags = btags = ""
2025-07-02 06:41:19.150             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.150             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.150                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.150                 if tag == 'replace':
2025-07-02 06:41:19.150                     atags += '^' * la
2025-07-02 06:41:19.150                     btags += '^' * lb
2025-07-02 06:41:19.150                 elif tag == 'delete':
2025-07-02 06:41:19.150                     atags += '-' * la
2025-07-02 06:41:19.150                 elif tag == 'insert':
2025-07-02 06:41:19.150                     btags += '+' * lb
2025-07-02 06:41:19.150                 elif tag == 'equal':
2025-07-02 06:41:19.150                     atags += ' ' * la
2025-07-02 06:41:19.150                     btags += ' ' * lb
2025-07-02 06:41:19.150                 else:
2025-07-02 06:41:19.150                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.150             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.150         else:
2025-07-02 06:41:19.151             # the synch pair is identical
2025-07-02 06:41:19.151             yield '  ' + aelt
2025-07-02 06:41:19.151
2025-07-02 06:41:19.151         # pump out diffs from after the synch point
2025-07-02 06:41:19.151 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.151
2025-07-02 06:41:19.151 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.151 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.151
2025-07-02 06:41:19.151 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.151 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.151 alo = 521, ahi = 1101
2025-07-02 06:41:19.151 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.151 blo = 521, bhi = 1101
2025-07-02 06:41:19.151
2025-07-02 06:41:19.151     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.151         g = []
2025-07-02 06:41:19.151         if alo < ahi:
2025-07-02 06:41:19.151             if blo < bhi:
2025-07-02 06:41:19.152                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.152             else:
2025-07-02 06:41:19.152                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.152         elif blo < bhi:
2025-07-02 06:41:19.152             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.152
2025-07-02 06:41:19.152 >       yield from g
2025-07-02 06:41:19.152
2025-07-02 06:41:19.152 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.152 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.152
2025-07-02 06:41:19.152 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.152 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.152 alo = 521, ahi = 1101
2025-07-02 06:41:19.152 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.152 blo = 521, bhi = 1101
2025-07-02 06:41:19.152
2025-07-02 06:41:19.152     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.152         r"""
2025-07-02 06:41:19.153         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.153         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.153         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.153         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.153
2025-07-02 06:41:19.153         Example:
2025-07-02 06:41:19.153
2025-07-02 06:41:19.153         >>> d = Differ()
2025-07-02 06:41:19.153         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.153         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.153         >>> print(''.join(results), end="")
2025-07-02 06:41:19.153         - abcDefghiJkl
2025-07-02 06:41:19.153         + abcdefGhijkl
2025-07-02 06:41:19.153         """
2025-07-02 06:41:19.153
2025-07-02 06:41:19.153         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.153         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.154         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.154         cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.154         eqi, eqj = None, None   # 1st indices of equal lines (if any)
2025-07-02 06:41:19.154
2025-07-02 06:41:19.154         # search for the pair that matches best without being identical
2025-07-02 06:41:19.154         # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 06:41:19.154         # on junk -- unless we have to)
2025-07-02 06:41:19.154         for j in range(blo, bhi):
2025-07-02 06:41:19.154             bj = b[j]
2025-07-02 06:41:19.154             cruncher.set_seq2(bj)
2025-07-02 06:41:19.154             for i in range(alo, ahi):
2025-07-02 06:41:19.154                 ai = a[i]
2025-07-02 06:41:19.154                 if ai == bj:
2025-07-02 06:41:19.154                     if eqi is None:
2025-07-02 06:41:19.154                         eqi, eqj = i, j
2025-07-02 06:41:19.154                     continue
2025-07-02 06:41:19.154                 cruncher.set_seq1(ai)
2025-07-02 06:41:19.154                 # computing similarity is expensive, so use the quick
2025-07-02 06:41:19.154                 # upper bounds first -- have seen this speed up messy
2025-07-02 06:41:19.155                 # compares by a factor of 3.
2025-07-02 06:41:19.155                 # note that ratio() is only expensive to compute the first
2025-07-02 06:41:19.155                 # time it's called on a sequence pair; the expensive part
2025-07-02 06:41:19.155                 # of the computation is cached by cruncher
2025-07-02 06:41:19.155                 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 06:41:19.155                       cruncher.quick_ratio() > best_ratio and \
2025-07-02 06:41:19.155                       cruncher.ratio() > best_ratio:
2025-07-02 06:41:19.155                     best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 06:41:19.155         if best_ratio < cutoff:
2025-07-02 06:41:19.155             # no non-identical "pretty close" pair
2025-07-02 06:41:19.155             if eqi is None:
2025-07-02 06:41:19.155                 # no identical pair either -- treat it as a straight replace
2025-07-02 06:41:19.155                 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.155                 return
2025-07-02 06:41:19.155             # no close pair, but an identical pair -- synch up on that
2025-07-02 06:41:19.155             best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 06:41:19.155         else:
2025-07-02 06:41:19.155             # there's a close pair, so forget the identical pair (if any)
2025-07-02 06:41:19.155             eqi = None
2025-07-02 06:41:19.156
2025-07-02 06:41:19.156         # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 06:41:19.156         # identical
2025-07-02 06:41:19.156
2025-07-02 06:41:19.156         # pump out diffs from before the synch point
2025-07-02 06:41:19.156         yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 06:41:19.156
2025-07-02 06:41:19.156         # do intraline marking on the synch pair
2025-07-02 06:41:19.156         aelt, belt = a[best_i], b[best_j]
2025-07-02 06:41:19.156         if eqi is None:
2025-07-02 06:41:19.156             # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 06:41:19.156             atags = btags = ""
2025-07-02 06:41:19.156             cruncher.set_seqs(aelt, belt)
2025-07-02 06:41:19.156             for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 06:41:19.156                 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 06:41:19.156                 if tag == 'replace':
2025-07-02 06:41:19.156                     atags += '^' * la
2025-07-02 06:41:19.156                     btags += '^' * lb
2025-07-02 06:41:19.156                 elif tag == 'delete':
2025-07-02 06:41:19.156                     atags += '-' * la
2025-07-02 06:41:19.157                 elif tag == 'insert':
2025-07-02 06:41:19.157                     btags += '+' * lb
2025-07-02 06:41:19.157                 elif tag == 'equal':
2025-07-02 06:41:19.157                     atags += ' ' * la
2025-07-02 06:41:19.157                     btags += ' ' * lb
2025-07-02 06:41:19.157                 else:
2025-07-02 06:41:19.157                     raise ValueError('unknown tag %r' % (tag,))
2025-07-02 06:41:19.157             yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 06:41:19.157         else:
2025-07-02 06:41:19.157             # the synch pair is identical
2025-07-02 06:41:19.157             yield '  ' + aelt
2025-07-02 06:41:19.157
2025-07-02 06:41:19.157         # pump out diffs from after the synch point
2025-07-02 06:41:19.157 >       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 06:41:19.157
2025-07-02 06:41:19.157 C:\Python3x\Lib\difflib.py:985:
2025-07-02 06:41:19.157 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.157
2025-07-02 06:41:19.157 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.157 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.158 alo = 522, ahi = 1101
2025-07-02 06:41:19.158 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.158 blo = 522, bhi = 1101
2025-07-02 06:41:19.158
2025-07-02 06:41:19.158     def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.158         g = []
2025-07-02 06:41:19.158         if alo < ahi:
2025-07-02 06:41:19.158             if blo < bhi:
2025-07-02 06:41:19.158                 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 06:41:19.158             else:
2025-07-02 06:41:19.158                 g = self._dump('-', a, alo, ahi)
2025-07-02 06:41:19.158         elif blo < bhi:
2025-07-02 06:41:19.158             g = self._dump('+', b, blo, bhi)
2025-07-02 06:41:19.158
2025-07-02 06:41:19.158 >       yield from g
2025-07-02 06:41:19.158
2025-07-02 06:41:19.158 C:\Python3x\Lib\difflib.py:997:
2025-07-02 06:41:19.158 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.158
2025-07-02 06:41:19.158 self = <difflib.Differ object at [hex]>
2025-07-02 06:41:19.159 a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
2025-07-02 06:41:19.159 alo = 522, ahi = 1101
2025-07-02 06:41:19.159 b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
2025-07-02 06:41:19.159 blo = 522, bhi = 1101
2025-07-02 06:41:19.159
2025-07-02 06:41:19.159     def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 06:41:19.159         r"""
2025-07-02 06:41:19.159         When replacing one block of lines with another, search the blocks
2025-07-02 06:41:19.159         for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 06:41:19.159         synch point, and intraline difference marking is done on the
2025-07-02 06:41:19.159         similar pair. Lots of work, but often worth it.
2025-07-02 06:41:19.159
2025-07-02 06:41:19.159         Example:
2025-07-02 06:41:19.159
2025-07-02 06:41:19.159         >>> d = Differ()
2025-07-02 06:41:19.159         >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 06:41:19.159         ...                            ['abcdefGhijkl\n'], 0, 1)
2025-07-02 06:41:19.159         >>> print(''.join(results), end="")
2025-07-02 06:41:19.159         - abcDefghiJkl
2025-07-02 06:41:19.160         + abcdefGhijkl
2025-07-02 06:41:19.160         """
2025-07-02 06:41:19.160
2025-07-02 06:41:19.160         # don't synch up unless the lines have a similarity score of at
2025-07-02 06:41:19.160         # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 06:41:19.160         best_ratio, cutoff = 0.74, 0.75
2025-07-02 06:41:19.160 >       cruncher = SequenceMatcher(self.charjunk)
2025-07-02 06:41:19.160
2025-07-02 06:41:19.160 C:\Python3x\Lib\difflib.py:915:
2025-07-02 06:41:19.160 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.160
2025-07-02 06:41:19.160 self = <difflib.SequenceMatcher object at [hex]>
2025-07-02 06:41:19.160 isjunk = <function IS_CHARACTER_JUNK at 0x000002A86576DC60>, a = '', b = ''
2025-07-02 06:41:19.160 autojunk = True
2025-07-02 06:41:19.160
2025-07-02 06:41:19.160     def __init__(self, isjunk=None, a='', b='', autojunk=True):
2025-07-02 06:41:19.160         """Construct a SequenceMatcher.
2025-07-02 06:41:19.161
2025-07-02 06:41:19.161         Optional arg isjunk is None (the default), or a one-argument
2025-07-02 06:41:19.161         function that takes a sequence element and returns true iff the
2025-07-02 06:41:19.161         element is junk.  None is equivalent to passing "lambda x: 0", i.e.
2025-07-02 06:41:19.161         no elements are considered to be junk.  For example, pass
2025-07-02 06:41:19.161             lambda x: x in " \\t"
2025-07-02 06:41:19.161         if you're comparing lines as sequences of characters, and don't
2025-07-02 06:41:19.161         want to synch up on blanks or hard tabs.
2025-07-02 06:41:19.161
2025-07-02 06:41:19.161         Optional arg a is the first of two sequences to be compared.  By
2025-07-02 06:41:19.161         default, an empty string.  The elements of a must be hashable.  See
2025-07-02 06:41:19.161         also .set_seqs() and .set_seq1().
2025-07-02 06:41:19.161
2025-07-02 06:41:19.161         Optional arg b is the second of two sequences to be compared.  By
2025-07-02 06:41:19.161         default, an empty string.  The elements of b must be hashable. See
2025-07-02 06:41:19.161         also .set_seqs() and .set_seq2().
2025-07-02 06:41:19.161
2025-07-02 06:41:19.161         Optional arg autojunk should be set to False to disable the
2025-07-02 06:41:19.162         "automatic junk heuristic" that treats popular elements as junk
2025-07-02 06:41:19.162         (see module documentation for more information).
2025-07-02 06:41:19.162         """
2025-07-02 06:41:19.162
2025-07-02 06:41:19.162         # Members:
2025-07-02 06:41:19.162         # a
2025-07-02 06:41:19.162         #      first sequence
2025-07-02 06:41:19.162         # b
2025-07-02 06:41:19.162         #      second sequence; differences are computed as "what do
2025-07-02 06:41:19.162         #      we need to do to 'a' to change it into 'b'?"
2025-07-02 06:41:19.162         # b2j
2025-07-02 06:41:19.162         #      for x in b, b2j[x] is a list of the indices (into b)
2025-07-02 06:41:19.162         #      at which x appears; junk and popular elements do not appear
2025-07-02 06:41:19.162         # fullbcount
2025-07-02 06:41:19.162         #      for x in b, fullbcount[x] == the number of times x
2025-07-02 06:41:19.162         #      appears in b; only materialized if really needed (used
2025-07-02 06:41:19.162         #      only for computing quick_ratio())
2025-07-02 06:41:19.162         # matching_blocks
2025-07-02 06:41:19.162         #      a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k];
2025-07-02 06:41:19.163         #      ascending & non-overlapping in i and in j; terminated by
2025-07-02 06:41:19.163         #      a dummy (len(a), len(b), 0) sentinel
2025-07-02 06:41:19.163         # opcodes
2025-07-02 06:41:19.163         #      a list of (tag, i1, i2, j1, j2) tuples, where tag is
2025-07-02 06:41:19.163         #      one of
2025-07-02 06:41:19.163         #          'replace'   a[i1:i2] should be replaced by b[j1:j2]
2025-07-02 06:41:19.163         #          'delete'    a[i1:i2] should be deleted
2025-07-02 06:41:19.163         #          'insert'    b[j1:j2] should be inserted
2025-07-02 06:41:19.163         #          'equal'     a[i1:i2] == b[j1:j2]
2025-07-02 06:41:19.163         # isjunk
2025-07-02 06:41:19.163         #      a user-supplied function taking a sequence element and
2025-07-02 06:41:19.163         #      returning true iff the element is "junk" -- this has
2025-07-02 06:41:19.163         #      subtle but helpful effects on the algorithm, which I'll
2025-07-02 06:41:19.163         #      get around to writing up someday <0.9 wink>.
2025-07-02 06:41:19.163         #      DON'T USE!  Only __chain_b uses this.  Use "in self.bjunk".
2025-07-02 06:41:19.163         # bjunk
2025-07-02 06:41:19.163         #      the items in b for which isjunk is True.
2025-07-02 06:41:19.163         # bpopular
2025-07-02 06:41:19.163         #      nonjunk items in b treated as junk by the heuristic (if used).
2025-07-02 06:41:19.163
2025-07-02 06:41:19.164         self.isjunk = isjunk
2025-07-02 06:41:19.164         self.a = self.b = None
2025-07-02 06:41:19.164         self.autojunk = autojunk
2025-07-02 06:41:19.164 >       self.set_seqs(a, b)
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164 C:\Python3x\Lib\difflib.py:182:
2025-07-02 06:41:19.164 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164 self = <difflib.SequenceMatcher object at [hex]>, a = '', b = ''
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164     def set_seqs(self, a, b):
2025-07-02 06:41:19.164         """Set the two sequences to be compared.
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164         >>> s = SequenceMatcher()
2025-07-02 06:41:19.164         >>> s.set_seqs("abcd", "bcde")
2025-07-02 06:41:19.164         >>> s.ratio()
2025-07-02 06:41:19.164         0.75
2025-07-02 06:41:19.164         """
2025-07-02 06:41:19.164
2025-07-02 06:41:19.164         self.set_seq1(a)
2025-07-02 06:41:19.164 >       self.set_seq2(b)
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165 C:\Python3x\Lib\difflib.py:194:
2025-07-02 06:41:19.165 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165 self = <difflib.SequenceMatcher object at [hex]>, b = ''
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165     def set_seq2(self, b):
2025-07-02 06:41:19.165         """Set the second sequence to be compared.
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165         The first sequence to be compared is not changed.
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165         >>> s = SequenceMatcher(None, "abcd", "bcde")
2025-07-02 06:41:19.165         >>> s.ratio()
2025-07-02 06:41:19.165         0.75
2025-07-02 06:41:19.165         >>> s.set_seq2("abcd")
2025-07-02 06:41:19.165         >>> s.ratio()
2025-07-02 06:41:19.165         1.0
2025-07-02 06:41:19.165         >>>
2025-07-02 06:41:19.165
2025-07-02 06:41:19.165         SequenceMatcher computes and caches detailed information about the
2025-07-02 06:41:19.166         second sequence, so if you want to compare one sequence S against
2025-07-02 06:41:19.166         many sequences, use .set_seq2(S) once and call .set_seq1(x)
2025-07-02 06:41:19.166         repeatedly for each of the other sequences.
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166         See also set_seqs() and set_seq1().
2025-07-02 06:41:19.166         """
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166         if b is self.b:
2025-07-02 06:41:19.166             return
2025-07-02 06:41:19.166         self.b = b
2025-07-02 06:41:19.166         self.matching_blocks = self.opcodes = None
2025-07-02 06:41:19.166         self.fullbcount = None
2025-07-02 06:41:19.166 >       self.__chain_b()
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166 C:\Python3x\Lib\difflib.py:248:
2025-07-02 06:41:19.166 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166 self = <difflib.SequenceMatcher object at [hex]>
2025-07-02 06:41:19.166
2025-07-02 06:41:19.166     def __chain_b(self):
2025-07-02 06:41:19.167         # Because isjunk is a user-defined (not C) function, and we test
2025-07-02 06:41:19.167         # for junk a LOT, it's important to minimize the number of calls.
2025-07-02 06:41:19.167         # Before the tricks described here, __chain_b was by far the most
2025-07-02 06:41:19.167         # time-consuming routine in the whole module!  If anyone sees
2025-07-02 06:41:19.167         # Jim Roskind, thank him again for profile.py -- I never would
2025-07-02 06:41:19.167         # have guessed that.
2025-07-02 06:41:19.167         # The first trick is to build b2j ignoring the possibility
2025-07-02 06:41:19.167         # of junk.  I.e., we don't call isjunk at all yet.  Throwing
2025-07-02 06:41:19.167         # out the junk later is much cheaper than building b2j "right"
2025-07-02 06:41:19.167         # from the start.
2025-07-02 06:41:19.167         b = self.b
2025-07-02 06:41:19.167         self.b2j = b2j = {}
2025-07-02 06:41:19.167
2025-07-02 06:41:19.167         for i, elt in enumerate(b):
2025-07-02 06:41:19.167             indices = b2j.setdefault(elt, [])
2025-07-02 06:41:19.167             indices.append(i)
2025-07-02 06:41:19.167
2025-07-02 06:41:19.167         # Purge junk elements
2025-07-02 06:41:19.167         self.bjunk = junk = set()
2025-07-02 06:41:19.167         isjunk = self.isjunk
2025-07-02 06:41:19.167         if isjunk:
2025-07-02 06:41:19.168 >           for elt in b2j.keys():
2025-07-02 06:41:19.168 E           RecursionError: maximum recursion depth exceeded while calling a Python object
2025-07-02 06:41:19.168
2025-07-02 06:41:19.168 C:\Python3x\Lib\difflib.py:288: RecursionError
2025-07-02 06:41:19.168 ---------------------------- Captured stdout setup ----------------------------
2025-07-02 06:41:19.168 Creating db: localhost:H:\QA\temp\qa2024.tmp\fbqa\test_1508\test.fdb [page_size=None, sql_dialect=None, charset='NONE', user=SYSDBA, password=masterkey]
3 #text
act = <firebird.qa.plugin.Action pytest object at [hex]>

    @pytest.mark.version('>=3')
    def test_1(act: Action):
        act.expected_stdout = expected_stdout
        act.execute()
>       assert act.clean_stdout == act.clean_expected_stdout

tests\bugs\core_2969_test.py:1211: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

ops = ('==',), results = (False,)
expls = ('%(py2)s\n{%(py2)s = %(py0)s.clean_stdout\n} == %(py6)s\n{%(py6)s = %(py4)s.clean_expected_stdout\n}',)
each_obj = ('WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1var...yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy')

    def _call_reprcompare(
        ops: Sequence[str],
        results: Sequence[bool],
        expls: Sequence[str],
        each_obj: Sequence[object],
    ) -> str:
        for i, res, expl in zip(range(len(ops)), results, expls):
            try:
                done = not res
            except Exception:
                done = True
            if done:
                break
        if util._reprcompare is not None:
>           custom = util._reprcompare(ops[i], each_obj[i], each_obj[i + 1])

C:\Python3x\Lib\site-packages\_pytest\assertion\rewrite.py:499: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

op = '=='
left = 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1var_...    yyy\n1var_997                        yyy\n1var_998                        yyy\n1var_999                        yyy'
right = 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1 var... yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy'

    def callbinrepr(op, left: object, right: object) -> Optional[str]:
        """Call the pytest_assertrepr_compare hook and prepare the result.
    
        This uses the first result from the hook and then ensures the
        following:
        * Overly verbose explanations are truncated unless configured otherwise
          (eg. if running in verbose mode).
        * Embedded newlines are escaped to help util.format_explanation()
          later.
        * If the rewrite mode is used embedded %-characters are replaced
          to protect later % formatting.
    
        The result can be formatted by util.format_explanation() for
        pretty printing.
        """
>       hook_result = ihook.pytest_assertrepr_compare(
            config=item.config, op=op, left=left, right=right
        )

C:\Python3x\Lib\site-packages\_pytest\assertion\__init__.py:141: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <HookCaller 'pytest_assertrepr_compare'>
kwargs = {'config': <_pytest.config.Config pytest object at [hex]>, 'left': 'WAS_OVERWRITTEN CTX_KEY                     ...yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy'}
firstresult = False

    def __call__(self, **kwargs: object) -> Any:
        """Call the hook.
    
        Only accepts keyword arguments, which should match the hook
        specification.
    
        Returns the result(s) of calling all registered plugins, see
        :ref:`calling`.
        """
        assert (
            not self.is_historic()
        ), "Cannot directly call a historic hook - use call_historic instead."
        self._verify_all_args_are_provided(kwargs)
        firstresult = self.spec.opts.get("firstresult", False) if self.spec else False
        # Copy because plugins may register other plugins during iteration (#438).
>       return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)

C:\Python3x\Lib\site-packages\pluggy\_hooks.py:501: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <_pytest.config.PytestPluginManager pytest object at [hex]>
hook_name = 'pytest_assertrepr_compare'
methods = [<HookImpl plugin_name='assertion', plugin=<module '_pytest.assertion' from 'C:\\Python3x\\Lib\\site-packages\\_pytest...plugin_name='firebird', plugin=<module 'firebird.qa.plugin' from 'H:\\QA\\firebird-qa\\src\\firebird\\qa\\plugin.py'>>]
kwargs = {'config': <_pytest.config.Config pytest object at [hex]>, 'left': 'WAS_OVERWRITTEN CTX_KEY                     ...yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy'}
firstresult = False

    def _hookexec(
        self,
        hook_name: str,
        methods: Sequence[HookImpl],
        kwargs: Mapping[str, object],
        firstresult: bool,
    ) -> object | list[object]:
        # called from all hookcaller instances.
        # enable_tracing will set its own wrapping function at self._inner_hookexec
>       return self._inner_hookexec(hook_name, methods, kwargs, firstresult)

C:\Python3x\Lib\site-packages\pluggy\_manager.py:119: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

config = <_pytest.config.Config pytest object at [hex]>, op = '=='
left = 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1var_...    yyy\n1var_997                        yyy\n1var_998                        yyy\n1var_999                        yyy'
right = 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL\n=============== ============================== =======\n1 var... yyy\n1 var_997                        yyy\n1 var_998                        yyy\n1 var_999                        yyy'

    def pytest_assertrepr_compare(config: Config, op: str, left: object, right: object) -> Optional[List[str]]:
        """Returns explanation for comparisons in failing assert expressions.
    
        If both objects are `str`, uses `difflib.ndiff` to provide explanation.
        """
        if isinstance(left, str) and isinstance(right, str) and op == "==":
            # 16.11.2023, pzotov: we have to put empty string at the beginning of each comparing lists.
            # Otherwise first diff will be at the same line as 'assert' phrase, which causes readability be poor.
            #
            left_lines = ['']
            left_lines.extend(left.splitlines())
            right_lines = ['']
            right_lines.extend(right.splitlines())
    
            # 16.11.2023, pzotov
            # ndiff output must be interpreted as following:
            #     * "E     - <some text>" ==> MISSED line (it was in EXPECTED text but absent in actual one).
            #     * "E     + <some_text>" ==> EXCESSIVE line (it is not in EXPECTED text but did appear in actual).
            # But for QA-purposes, this output must answer the question:
            #     "what must be changed in ACTUAL output so that it became equal to EXPECTED"
            #     (i.e. how to "REVERT" actual back to expected).
            # In order to see such result, we have to specify 'right_lines' to the 1st argument that is passed to ndiff().
            # ::: NB :::
            # We assume that all tests are written so that ACTUAL output is left side in 'assert' statement and EXPECTED
            # is right side, e.g: assert act.clean_stdout == act.clean_expected_stdout
            # This requirement is CRUCIAL if we use ndiff() instead of default pytest comparison method!
            #
>           return list(ndiff(right_lines, left_lines))

src\firebird\qa\plugin.py:608: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]

    def compare(self, a, b):
        r"""
        Compare two sequences of lines; generate the resulting delta.
    
        Each sequence must contain individual single-line strings ending with
        newlines. Such sequences can be obtained from the `readlines()` method
        of file-like objects.  The delta generated also consists of newline-
        terminated strings, ready to be printed as-is via the writelines()
        method of a file-like object.
    
        Example:
    
        >>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True),
        ...                                'ore\ntree\nemu\n'.splitlines(True))),
        ...       end="")
        - one
        + ore
        - two
        - three
        + tree
        + emu
        """
    
        cruncher = SequenceMatcher(self.linejunk, a, b)
        for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
            if tag == 'replace':
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            elif tag == 'delete':
                g = self._dump('-', a, alo, ahi)
            elif tag == 'insert':
                g = self._dump('+', b, blo, bhi)
            elif tag == 'equal':
                g = self._dump(' ', a, alo, ahi)
            else:
                raise ValueError('unknown tag %r' % (tag,))
    
>           yield from g

C:\Python3x\Lib\difflib.py:872: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 3, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 3, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 4, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 4, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 4, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 4, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 5, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 5, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 5, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 5, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 6, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 6, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 6, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 6, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 7, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 7, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 7, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 7, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 8, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 8, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 8, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 8, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 9, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 9, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 9, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 9, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 10, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 10, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 10, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 10, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 11, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 11, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 11, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 11, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 12, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 12, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 12, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 12, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 13, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 13, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 13, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 13, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 14, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 14, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 14, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 14, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 15, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 15, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 15, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 15, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 16, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 16, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 16, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 16, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 17, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 17, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 17, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 17, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 18, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 18, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 18, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 18, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 19, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 19, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 19, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 19, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 20, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 20, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 20, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 20, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 21, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 21, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 21, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 21, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 22, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 22, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 22, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 22, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 23, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 23, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 23, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 23, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 26, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 26, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 26, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 26, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 27, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 27, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 27, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 27, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 28, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 28, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 28, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 28, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 29, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 29, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 29, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 29, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 30, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 30, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 30, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 30, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 31, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 31, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 31, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 31, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 32, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 32, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 32, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 32, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 33, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 33, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 33, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 33, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 34, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 34, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 34, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 34, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 35, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 35, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 35, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 35, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 36, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 36, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 36, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 36, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 37, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 37, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 37, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 37, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 38, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 38, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 38, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 38, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 39, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 39, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 39, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 39, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 40, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 40, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 40, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 40, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 41, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 41, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 41, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 41, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 42, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 42, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 42, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 42, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 43, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 43, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 43, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 43, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 44, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 44, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 44, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 44, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 45, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 45, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 45, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 45, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 48, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 48, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 48, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 48, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 49, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 49, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 49, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 49, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 50, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 50, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 50, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 50, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 51, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 51, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 51, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 51, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 52, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 52, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 52, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 52, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 53, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 53, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 53, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 53, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 54, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 54, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 54, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 54, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 55, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 55, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 55, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 55, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 56, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 56, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 56, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 56, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 57, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 57, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 57, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 57, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 58, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 58, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 58, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 58, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 59, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 59, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 59, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 59, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 60, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 60, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 60, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 60, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 61, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 61, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 61, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 61, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 62, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 62, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 62, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 62, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 63, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 63, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 63, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 63, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 64, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 64, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 64, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 64, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 65, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 65, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 65, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 65, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 66, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 66, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 66, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 66, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 67, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 67, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 67, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 67, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 70, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 70, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 70, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 70, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 71, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 71, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 71, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 71, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 72, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 72, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 72, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 72, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 73, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 73, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 73, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 73, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 74, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 74, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 74, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 74, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 75, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 75, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 75, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 75, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 76, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 76, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 76, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 76, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 77, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 77, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 77, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 77, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 78, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 78, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 78, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 78, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 79, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 79, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 79, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 79, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 80, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 80, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 80, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 80, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 81, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 81, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 81, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 81, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 82, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 82, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 82, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 82, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 83, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 83, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 83, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 83, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 84, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 84, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 84, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 84, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 85, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 85, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 85, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 85, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 86, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 86, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 86, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 86, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 87, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 87, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 87, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 87, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 88, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 88, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 88, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 88, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 89, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 89, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 89, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 89, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 92, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 92, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 92, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 92, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 93, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 93, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 93, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 93, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 94, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 94, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 94, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 94, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 95, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 95, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 95, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 95, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 96, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 96, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 96, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 96, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 97, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 97, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 97, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 97, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 98, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 98, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 98, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 98, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 99, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 99, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 99, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 99, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 100, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 100, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 100, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 100, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 101, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 101, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 101, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 101, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 102, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 102, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 102, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 102, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 103, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 103, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 103, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 103, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 104, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 104, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 104, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 104, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 105, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 105, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 105, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 105, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 106, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 106, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 106, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 106, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 107, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 107, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 107, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 107, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 108, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 108, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 108, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 108, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 109, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 109, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 109, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 109, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 110, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 110, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 110, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 110, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 111, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 111, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 111, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 111, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 114, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 114, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 114, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 114, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 115, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 115, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 115, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 115, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 116, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 116, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 116, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 116, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 117, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 117, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 117, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 117, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 118, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 118, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 118, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 118, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 119, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 119, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 119, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 119, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 120, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 120, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 120, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 120, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 121, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 121, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 121, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 121, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 122, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 122, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 122, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 122, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 123, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 123, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 123, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 123, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 124, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 124, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 124, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 124, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 125, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 125, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 125, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 125, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 126, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 126, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 126, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 126, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 127, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 127, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 127, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 127, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 128, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 128, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 128, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 128, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 129, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 129, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 129, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 129, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 130, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 130, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 130, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 130, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 131, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 131, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 131, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 131, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 132, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 132, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 132, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 132, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 133, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 133, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 133, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 133, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 136, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 136, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 136, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 136, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 137, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 137, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 137, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 137, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 138, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 138, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 138, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 138, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 139, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 139, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 139, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 139, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 140, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 140, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 140, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 140, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 141, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 141, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 141, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 141, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 142, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 142, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 142, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 142, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 143, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 143, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 143, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 143, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 144, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 144, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 144, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 144, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 145, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 145, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 145, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 145, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 146, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 146, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 146, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 146, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 147, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 147, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 147, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 147, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 148, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 148, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 148, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 148, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 149, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 149, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 149, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 149, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 150, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 150, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 150, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 150, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 151, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 151, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 151, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 151, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 152, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 152, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 152, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 152, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 153, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 153, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 153, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 153, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 154, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 154, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 154, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 154, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 155, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 155, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 155, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 155, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 158, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 158, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 158, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 158, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 159, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 159, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 159, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 159, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 160, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 160, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 160, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 160, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 161, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 161, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 161, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 161, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 162, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 162, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 162, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 162, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 163, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 163, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 163, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 163, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 164, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 164, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 164, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 164, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 165, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 165, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 165, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 165, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 166, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 166, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 166, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 166, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 167, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 167, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 167, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 167, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 168, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 168, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 168, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 168, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 169, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 169, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 169, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 169, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 170, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 170, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 170, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 170, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 171, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 171, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 171, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 171, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 172, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 172, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 172, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 172, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 173, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 173, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 173, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 173, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 174, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 174, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 174, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 174, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 175, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 175, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 175, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 175, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 176, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 176, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 176, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 176, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 177, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 177, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 177, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 177, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 180, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 180, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 180, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 180, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 181, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 181, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 181, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 181, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 182, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 182, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 182, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 182, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 183, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 183, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 183, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 183, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 184, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 184, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 184, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 184, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 185, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 185, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 185, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 185, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 186, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 186, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 186, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 186, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 187, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 187, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 187, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 187, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 188, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 188, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 188, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 188, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 189, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 189, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 189, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 189, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 190, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 190, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 190, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 190, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 191, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 191, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 191, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 191, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 192, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 192, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 192, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 192, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 193, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 193, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 193, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 193, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 194, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 194, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 194, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 194, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 195, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 195, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 195, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 195, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 196, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 196, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 196, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 196, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 197, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 197, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 197, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 197, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 198, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 198, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 198, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 198, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 199, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 199, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 199, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 199, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 202, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 202, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 202, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 202, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 203, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 203, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 203, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 203, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 204, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 204, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 204, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 204, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 205, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 205, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 205, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 205, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 206, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 206, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 206, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 206, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 207, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 207, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 207, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 207, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 208, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 208, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 208, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 208, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 209, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 209, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 209, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 209, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 210, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 210, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 210, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 210, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 211, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 211, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 211, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 211, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 212, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 212, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 212, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 212, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 213, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 213, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 213, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 213, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 214, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 214, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 214, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 214, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 215, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 215, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 215, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 215, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 216, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 216, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 216, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 216, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 217, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 217, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 217, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 217, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 218, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 218, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 218, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 218, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 219, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 219, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 219, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 219, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 220, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 220, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 220, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 220, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 221, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 221, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 221, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 221, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 224, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 224, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 224, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 224, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 225, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 225, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 225, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 225, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 226, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 226, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 226, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 226, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 227, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 227, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 227, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 227, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 228, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 228, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 228, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 228, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 229, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 229, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 229, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 229, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 230, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 230, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 230, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 230, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 231, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 231, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 231, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 231, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 232, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 232, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 232, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 232, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 233, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 233, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 233, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 233, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 234, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 234, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 234, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 234, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 235, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 235, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 235, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 235, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 236, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 236, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 236, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 236, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 237, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 237, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 237, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 237, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 238, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 238, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 238, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 238, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 239, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 239, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 239, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 239, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 240, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 240, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 240, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 240, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 241, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 241, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 241, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 241, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 242, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 242, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 242, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 242, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 243, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 243, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 243, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 243, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 246, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 246, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 246, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 246, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 247, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 247, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 247, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 247, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 248, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 248, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 248, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 248, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 249, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 249, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 249, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 249, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 250, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 250, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 250, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 250, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 251, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 251, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 251, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 251, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 252, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 252, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 252, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 252, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 253, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 253, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 253, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 253, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 254, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 254, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 254, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 254, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 255, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 255, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 255, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 255, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 256, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 256, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 256, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 256, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 257, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 257, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 257, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 257, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 258, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 258, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 258, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 258, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 259, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 259, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 259, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 259, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 260, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 260, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 260, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 260, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 261, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 261, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 261, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 261, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 262, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 262, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 262, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 262, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 263, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 263, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 263, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 263, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 264, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 264, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 264, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 264, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 265, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 265, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 265, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 265, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 268, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 268, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 268, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 268, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 269, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 269, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 269, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 269, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 270, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 270, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 270, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 270, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 271, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 271, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 271, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 271, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 272, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 272, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 272, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 272, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 273, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 273, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 273, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 273, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 274, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 274, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 274, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 274, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 275, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 275, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 275, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 275, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 276, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 276, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 276, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 276, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 277, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 277, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 277, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 277, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 278, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 278, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 278, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 278, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 279, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 279, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 279, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 279, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 280, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 280, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 280, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 280, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 281, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 281, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 281, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 281, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 282, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 282, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 282, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 282, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 283, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 283, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 283, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 283, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 284, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 284, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 284, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 284, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 285, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 285, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 285, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 285, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 286, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 286, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 286, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 286, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 287, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 287, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 287, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 287, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 290, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 290, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 290, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 290, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 291, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 291, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 291, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 291, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 292, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 292, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 292, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 292, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 293, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 293, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 293, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 293, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 294, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 294, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 294, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 294, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 295, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 295, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 295, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 295, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 296, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 296, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 296, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 296, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 297, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 297, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 297, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 297, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 298, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 298, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 298, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 298, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 299, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 299, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 299, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 299, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 300, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 300, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 300, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 300, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 301, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 301, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 301, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 301, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 302, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 302, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 302, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 302, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 303, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 303, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 303, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 303, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 304, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 304, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 304, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 304, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 305, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 305, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 305, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 305, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 306, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 306, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 306, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 306, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 307, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 307, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 307, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 307, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 308, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 308, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 308, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 308, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 309, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 309, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 309, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 309, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 312, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 312, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 312, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 312, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 313, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 313, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 313, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 313, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 314, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 314, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 314, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 314, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 315, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 315, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 315, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 315, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 316, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 316, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 316, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 316, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 317, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 317, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 317, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 317, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 318, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 318, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 318, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 318, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 319, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 319, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 319, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 319, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 320, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 320, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 320, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 320, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 321, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 321, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 321, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 321, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 322, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 322, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 322, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 322, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 323, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 323, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 323, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 323, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 324, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 324, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 324, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 324, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 325, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 325, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 325, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 325, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 326, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 326, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 326, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 326, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 327, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 327, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 327, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 327, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 328, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 328, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 328, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 328, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 329, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 329, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 329, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 329, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 330, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 330, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 330, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 330, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 331, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 331, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 331, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 331, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 334, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 334, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 334, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 334, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 335, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 335, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 335, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 335, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 336, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 336, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 336, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 336, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 337, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 337, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 337, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 337, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 338, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 338, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 338, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 338, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 339, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 339, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 339, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 339, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 340, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 340, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 340, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 340, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 341, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 341, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 341, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 341, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 342, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 342, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 342, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 342, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 343, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 343, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 343, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 343, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 344, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 344, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 344, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 344, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 345, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 345, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 345, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 345, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 346, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 346, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 346, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 346, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 347, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 347, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 347, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 347, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 348, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 348, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 348, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 348, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 349, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 349, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 349, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 349, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 350, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 350, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 350, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 350, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 351, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 351, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 351, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 351, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 352, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 352, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 352, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 352, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 353, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 353, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 353, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 353, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 356, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 356, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 356, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 356, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 357, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 357, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 357, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 357, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 358, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 358, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 358, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 358, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 359, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 359, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 359, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 359, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 360, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 360, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 360, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 360, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 361, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 361, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 361, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 361, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 362, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 362, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 362, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 362, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 363, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 363, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 363, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 363, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 364, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 364, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 364, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 364, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 365, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 365, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 365, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 365, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 366, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 366, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 366, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 366, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 367, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 367, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 367, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 367, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 368, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 368, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 368, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 368, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 369, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 369, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 369, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 369, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 370, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 370, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 370, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 370, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 371, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 371, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 371, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 371, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 372, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 372, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 372, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 372, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 373, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 373, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 373, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 373, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 374, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 374, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 374, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 374, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 375, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 375, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 375, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 375, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 378, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 378, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 378, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 378, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 379, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 379, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 379, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 379, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 380, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 380, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 380, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 380, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 381, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 381, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 381, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 381, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 382, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 382, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 382, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 382, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 383, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 383, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 383, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 383, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 384, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 384, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 384, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 384, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 385, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 385, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 385, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 385, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 386, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 386, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 386, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 386, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 387, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 387, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 387, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 387, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 388, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 388, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 388, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 388, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 389, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 389, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 389, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 389, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 390, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 390, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 390, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 390, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 391, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 391, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 391, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 391, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 392, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 392, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 392, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 392, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 393, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 393, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 393, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 393, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 394, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 394, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 394, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 394, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 395, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 395, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 395, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 395, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 396, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 396, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 396, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 396, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 397, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 397, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 397, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 397, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 400, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 400, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 400, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 400, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 401, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 401, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 401, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 401, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 402, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 402, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 402, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 402, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 403, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 403, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 403, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 403, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 404, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 404, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 404, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 404, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 405, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 405, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 405, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 405, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 406, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 406, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 406, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 406, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 407, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 407, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 407, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 407, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 408, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 408, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 408, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 408, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 409, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 409, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 409, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 409, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 410, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 410, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 410, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 410, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 411, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 411, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 411, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 411, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 412, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 412, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 412, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 412, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 413, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 413, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 413, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 413, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 414, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 414, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 414, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 414, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 415, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 415, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 415, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 415, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 416, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 416, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 416, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 416, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 417, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 417, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 417, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 417, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 418, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 418, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 418, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 418, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 419, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 419, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 419, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 419, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 422, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 422, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 422, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 422, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 423, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 423, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 423, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 423, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 424, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 424, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 424, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 424, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 425, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 425, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 425, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 425, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 426, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 426, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 426, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 426, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 427, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 427, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 427, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 427, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 428, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 428, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 428, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 428, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 429, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 429, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 429, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 429, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 430, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 430, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 430, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 430, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 431, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 431, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 431, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 431, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 432, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 432, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 432, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 432, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 433, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 433, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 433, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 433, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 434, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 434, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 434, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 434, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 435, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 435, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 435, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 435, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 436, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 436, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 436, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 436, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 437, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 437, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 437, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 437, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 438, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 438, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 438, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 438, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 439, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 439, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 439, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 439, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 440, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 440, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 440, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 440, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 441, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 441, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 441, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 441, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 444, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 444, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 444, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 444, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 445, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 445, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 445, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 445, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 446, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 446, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 446, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 446, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 447, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 447, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 447, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 447, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 448, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 448, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 448, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 448, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 449, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 449, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 449, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 449, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 450, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 450, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 450, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 450, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 451, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 451, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 451, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 451, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 452, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 452, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 452, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 452, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 453, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 453, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 453, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 453, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 454, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 454, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 454, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 454, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 455, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 455, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 455, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 455, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 456, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 456, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 456, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 456, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 457, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 457, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 457, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 457, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 458, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 458, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 458, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 458, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 459, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 459, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 459, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 459, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 460, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 460, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 460, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 460, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 461, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 461, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 461, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 461, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 462, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 462, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 462, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 462, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 463, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 463, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 463, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 463, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 466, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 466, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 466, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 466, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 467, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 467, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 467, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 467, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 468, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 468, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 468, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 468, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 469, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 469, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 469, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 469, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 470, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 470, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 470, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 470, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 471, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 471, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 471, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 471, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 472, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 472, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 472, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 472, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 473, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 473, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 473, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 473, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 474, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 474, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 474, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 474, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 475, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 475, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 475, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 475, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 476, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 476, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 476, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 476, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 477, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 477, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 477, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 477, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 478, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 478, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 478, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 478, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 479, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 479, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 479, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 479, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 480, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 480, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 480, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 480, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 481, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 481, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 481, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 481, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 482, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 482, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 482, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 482, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 483, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 483, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 483, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 483, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 484, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 484, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 484, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 484, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 485, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 485, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 485, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 485, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 488, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 488, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 488, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 488, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 489, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 489, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 489, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 489, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 490, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 490, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 490, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 490, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 491, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 491, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 491, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 491, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 492, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 492, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 492, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 492, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 493, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 493, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 493, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 493, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 494, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 494, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 494, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 494, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 495, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 495, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 495, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 495, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 496, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 496, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 496, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 496, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 497, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 497, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 497, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 497, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 498, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 498, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 498, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 498, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 499, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 499, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 499, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 499, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 500, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 500, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 500, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 500, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 501, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 501, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 501, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 501, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 502, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 502, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 502, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 502, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 503, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 503, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 503, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 503, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 504, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 504, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 504, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 504, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 505, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 505, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 505, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 505, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 506, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 506, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 506, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 506, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 507, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 507, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 507, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 507, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 510, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 510, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 510, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 510, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 511, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 511, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 511, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 511, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 512, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 512, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 512, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 512, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 513, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 513, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 513, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 513, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 514, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 514, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 514, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 514, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 515, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 515, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 515, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 515, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 516, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 516, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 516, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 516, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 517, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 517, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 517, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 517, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 518, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 518, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 518, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 518, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 519, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 519, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 519, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 519, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 520, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 520, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 520, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 520, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 521, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 521, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 521, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 521, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)
    
        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None
    
        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical
    
        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
    
        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt
    
        # pump out diffs from after the synch point
>       yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

C:\Python3x\Lib\difflib.py:985: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 522, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 522, bhi = 1101

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)
    
>       yield from g

C:\Python3x\Lib\difflib.py:997: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.Differ pytest object at [hex]>
a = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...r_0                          yyy', '1 var_1                          yyy', '1 var_2                          yyy', ...]
alo = 522, ahi = 1101
b = ['', 'WAS_OVERWRITTEN CTX_KEY                        CTX_VAL', '=============== ============================== =======...var_0                          yyy', '1var_1                          yyy', '1var_2                          yyy', ...]
blo = 522, bhi = 1101

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.
    
        Example:
    
        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        + abcdefGhijkl
        """
    
        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
>       cruncher = SequenceMatcher(self.charjunk)

C:\Python3x\Lib\difflib.py:915: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.SequenceMatcher pytest object at [hex]>
isjunk = <function IS_CHARACTER_JUNK at 0x000002A86576DC60>, a = '', b = ''
autojunk = True

    def __init__(self, isjunk=None, a='', b='', autojunk=True):
        """Construct a SequenceMatcher.
    
        Optional arg isjunk is None (the default), or a one-argument
        function that takes a sequence element and returns true iff the
        element is junk.  None is equivalent to passing "lambda x: 0", i.e.
        no elements are considered to be junk.  For example, pass
            lambda x: x in " \\t"
        if you're comparing lines as sequences of characters, and don't
        want to synch up on blanks or hard tabs.
    
        Optional arg a is the first of two sequences to be compared.  By
        default, an empty string.  The elements of a must be hashable.  See
        also .set_seqs() and .set_seq1().
    
        Optional arg b is the second of two sequences to be compared.  By
        default, an empty string.  The elements of b must be hashable. See
        also .set_seqs() and .set_seq2().
    
        Optional arg autojunk should be set to False to disable the
        "automatic junk heuristic" that treats popular elements as junk
        (see module documentation for more information).
        """
    
        # Members:
        # a
        #      first sequence
        # b
        #      second sequence; differences are computed as "what do
        #      we need to do to 'a' to change it into 'b'?"
        # b2j
        #      for x in b, b2j[x] is a list of the indices (into b)
        #      at which x appears; junk and popular elements do not appear
        # fullbcount
        #      for x in b, fullbcount[x] == the number of times x
        #      appears in b; only materialized if really needed (used
        #      only for computing quick_ratio())
        # matching_blocks
        #      a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k];
        #      ascending & non-overlapping in i and in j; terminated by
        #      a dummy (len(a), len(b), 0) sentinel
        # opcodes
        #      a list of (tag, i1, i2, j1, j2) tuples, where tag is
        #      one of
        #          'replace'   a[i1:i2] should be replaced by b[j1:j2]
        #          'delete'    a[i1:i2] should be deleted
        #          'insert'    b[j1:j2] should be inserted
        #          'equal'     a[i1:i2] == b[j1:j2]
        # isjunk
        #      a user-supplied function taking a sequence element and
        #      returning true iff the element is "junk" -- this has
        #      subtle but helpful effects on the algorithm, which I'll
        #      get around to writing up someday <0.9 wink>.
        #      DON'T USE!  Only __chain_b uses this.  Use "in self.bjunk".
        # bjunk
        #      the items in b for which isjunk is True.
        # bpopular
        #      nonjunk items in b treated as junk by the heuristic (if used).
    
        self.isjunk = isjunk
        self.a = self.b = None
        self.autojunk = autojunk
>       self.set_seqs(a, b)

C:\Python3x\Lib\difflib.py:182: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.SequenceMatcher pytest object at [hex]>, a = '', b = ''

    def set_seqs(self, a, b):
        """Set the two sequences to be compared.
    
        >>> s = SequenceMatcher()
        >>> s.set_seqs("abcd", "bcde")
        >>> s.ratio()
        0.75
        """
    
        self.set_seq1(a)
>       self.set_seq2(b)

C:\Python3x\Lib\difflib.py:194: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.SequenceMatcher pytest object at [hex]>, b = ''

    def set_seq2(self, b):
        """Set the second sequence to be compared.
    
        The first sequence to be compared is not changed.
    
        >>> s = SequenceMatcher(None, "abcd", "bcde")
        >>> s.ratio()
        0.75
        >>> s.set_seq2("abcd")
        >>> s.ratio()
        1.0
        >>>
    
        SequenceMatcher computes and caches detailed information about the
        second sequence, so if you want to compare one sequence S against
        many sequences, use .set_seq2(S) once and call .set_seq1(x)
        repeatedly for each of the other sequences.
    
        See also set_seqs() and set_seq1().
        """
    
        if b is self.b:
            return
        self.b = b
        self.matching_blocks = self.opcodes = None
        self.fullbcount = None
>       self.__chain_b()

C:\Python3x\Lib\difflib.py:248: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <difflib.SequenceMatcher pytest object at [hex]>

    def __chain_b(self):
        # Because isjunk is a user-defined (not C) function, and we test
        # for junk a LOT, it's important to minimize the number of calls.
        # Before the tricks described here, __chain_b was by far the most
        # time-consuming routine in the whole module!  If anyone sees
        # Jim Roskind, thank him again for profile.py -- I never would
        # have guessed that.
        # The first trick is to build b2j ignoring the possibility
        # of junk.  I.e., we don't call isjunk at all yet.  Throwing
        # out the junk later is much cheaper than building b2j "right"
        # from the start.
        b = self.b
        self.b2j = b2j = {}
    
        for i, elt in enumerate(b):
            indices = b2j.setdefault(elt, [])
            indices.append(i)
    
        # Purge junk elements
        self.bjunk = junk = set()
        isjunk = self.isjunk
        if isjunk:
>           for elt in b2j.keys():
E           RecursionError: maximum recursion depth exceeded while calling a Python object

C:\Python3x\Lib\difflib.py:288: RecursionError
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):